Guest User

qemu-vmapple

a guest
Aug 26th, 2024
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 98.96 KB | Software | 0 0
  1. diff --git a/MAINTAINERS b/MAINTAINERS
  2. index 6111b6b4d9..3104e58eff 100644
  3. --- a/MAINTAINERS
  4. +++ b/MAINTAINERS
  5. @@ -2573,6 +2573,12 @@ F: hw/usb/canokey.c
  6. F: hw/usb/canokey.h
  7. F: docs/system/devices/canokey.rst
  8.  
  9. +VMapple
  10. +M: Alexander Graf <[email protected]>
  11. +S: Maintained
  12. +F: hw/vmapple/*
  13. +F: include/hw/vmapple/*
  14. +
  15. Subsystems
  16. ----------
  17. Overall Audio backends
  18. diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
  19. index a44cf1c144..dd285c694c 100644
  20. --- a/accel/hvf/hvf-accel-ops.c
  21. +++ b/accel/hvf/hvf-accel-ops.c
  22. @@ -88,7 +88,7 @@ struct mac_slot {
  23. uint64_t gva;
  24. };
  25.  
  26. -struct mac_slot mac_slots[32];
  27. +struct mac_slot mac_slots[512];
  28.  
  29. static int do_hvf_set_memory(hvf_slot *slot, hv_memory_flags_t flags)
  30. {
  31. diff --git a/hw/Kconfig b/hw/Kconfig
  32. index ba62ff6417..d99854afdd 100644
  33. --- a/hw/Kconfig
  34. +++ b/hw/Kconfig
  35. @@ -41,6 +41,7 @@ source tpm/Kconfig
  36. source usb/Kconfig
  37. source virtio/Kconfig
  38. source vfio/Kconfig
  39. +source vmapple/Kconfig
  40. source xen/Kconfig
  41. source watchdog/Kconfig
  42.  
  43. diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
  44. index bc89eb4806..a786849238 100644
  45. --- a/hw/arm/sbsa-ref.c
  46. +++ b/hw/arm/sbsa-ref.c
  47. @@ -681,7 +681,7 @@ static void create_pcie(SBSAMachineState *sms)
  48. /* Map IO port space */
  49. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
  50.  
  51. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  52. + for (i = 0; i < PCI_NUM_PINS; i++) {
  53. sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
  54. qdev_get_gpio_in(sms->gic, irq + i));
  55. gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
  56. diff --git a/hw/arm/virt.c b/hw/arm/virt.c
  57. index 7d9dbc2663..40ce59a68a 100644
  58. --- a/hw/arm/virt.c
  59. +++ b/hw/arm/virt.c
  60. @@ -1467,7 +1467,7 @@ static void create_pcie(VirtMachineState *vms)
  61. /* Map IO port space */
  62. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
  63.  
  64. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  65. + for (i = 0; i < PCI_NUM_PINS; i++) {
  66. sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
  67. qdev_get_gpio_in(vms->gic, irq + i));
  68. gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
  69. diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
  70. index 39e7f23fab..76b85bb3cb 100644
  71. --- a/hw/block/virtio-blk.c
  72. +++ b/hw/block/virtio-blk.c
  73. @@ -1120,6 +1120,20 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
  74.  
  75. break;
  76. }
  77. + case VIRTIO_BLK_T_APPLE1:
  78. + {
  79. + if (s->conf.x_apple_type) {
  80. + /* Only valid on Apple Virtio */
  81. + char buf[iov_size(in_iov, in_num)];
  82. + memset(buf, 0, sizeof(buf));
  83. + iov_from_buf(in_iov, in_num, 0, buf, sizeof(buf));
  84. + virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
  85. + } else {
  86. + virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
  87. + }
  88. + virtio_blk_free_request(req);
  89. + break;
  90. + }
  91. default:
  92. virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
  93. virtio_blk_free_request(req);
  94. @@ -1351,6 +1365,10 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
  95. } else {
  96. blkcfg.zoned.model = VIRTIO_BLK_Z_NONE;
  97. }
  98. + if (s->conf.x_apple_type) {
  99. + /* Apple abuses the same location for its type id */
  100. + blkcfg.max_secure_erase_sectors = s->conf.x_apple_type;
  101. + }
  102. memcpy(config, &blkcfg, s->config_size);
  103. }
  104.  
  105. @@ -1625,6 +1643,10 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
  106.  
  107. s->config_size = virtio_get_config_size(&virtio_blk_cfg_size_params,
  108. s->host_features);
  109. + if (s->conf.x_apple_type) {
  110. + /* Apple Virtio puts the blk type at 0x3c, make sure we have space. */
  111. + s->config_size = MAX(s->config_size, 0x3d);
  112. + }
  113. virtio_init(vdev, VIRTIO_ID_BLOCK, s->config_size);
  114.  
  115. s->blk = conf->conf.blk;
  116. @@ -1734,6 +1756,7 @@ static Property virtio_blk_properties[] = {
  117. conf.max_write_zeroes_sectors, BDRV_REQUEST_MAX_SECTORS),
  118. DEFINE_PROP_BOOL("x-enable-wce-if-config-wce", VirtIOBlock,
  119. conf.x_enable_wce_if_config_wce, true),
  120. + DEFINE_PROP_UINT32("x-apple-type", VirtIOBlock, conf.x_apple_type, 0),
  121. DEFINE_PROP_END_OF_LIST(),
  122. };
  123.  
  124. diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
  125. index 7227a2156c..9ca007b870 100644
  126. --- a/hw/i386/microvm.c
  127. +++ b/hw/i386/microvm.c
  128. @@ -139,7 +139,7 @@ static void create_gpex(MicrovmMachineState *mms)
  129. mms->gpex.mmio64.base, mmio64_alias);
  130. }
  131.  
  132. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  133. + for (i = 0; i < PCI_NUM_PINS; i++) {
  134. sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
  135. x86ms->gsi[mms->gpex.irq + i]);
  136. }
  137. diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
  138. index e19b042ce8..67ff03cb10 100644
  139. --- a/hw/loongarch/virt.c
  140. +++ b/hw/loongarch/virt.c
  141. @@ -533,7 +533,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *
  142. memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE,
  143. pio_alias);
  144.  
  145. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  146. + for (i = 0; i < PCI_NUM_PINS; i++) {
  147. sysbus_connect_irq(d, i,
  148. qdev_get_gpio_in(pch_pic, 16 + i));
  149. gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
  150. diff --git a/hw/meson.build b/hw/meson.build
  151. index c7ac7d3d75..e156a6618f 100644
  152. --- a/hw/meson.build
  153. +++ b/hw/meson.build
  154. @@ -40,6 +40,7 @@ subdir('tpm')
  155. subdir('usb')
  156. subdir('vfio')
  157. subdir('virtio')
  158. +subdir('vmapple')
  159. subdir('watchdog')
  160. subdir('xen')
  161. subdir('xenpv')
  162. diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
  163. index 3ad0a223df..c6162c8efc 100644
  164. --- a/hw/mips/loongson3_virt.c
  165. +++ b/hw/mips/loongson3_virt.c
  166. @@ -438,7 +438,7 @@ static inline void loongson3_virt_devices_init(MachineState *machine,
  167. virt_memmap[VIRT_PCIE_PIO].base, s->pio_alias);
  168. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, virt_memmap[VIRT_PCIE_PIO].base);
  169.  
  170. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  171. + for (i = 0; i < PCI_NUM_PINS; i++) {
  172. irq = qdev_get_gpio_in(pic, PCIE_IRQ_BASE + i);
  173. sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
  174. gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ_BASE + i);
  175. diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
  176. index 6996d265e4..b69746a60a 100644
  177. --- a/hw/misc/Kconfig
  178. +++ b/hw/misc/Kconfig
  179. @@ -125,6 +125,10 @@ config PVPANIC_ISA
  180. depends on ISA_BUS
  181. select PVPANIC_COMMON
  182.  
  183. +config PVPANIC_MMIO
  184. + bool
  185. + select PVPANIC_COMMON
  186. +
  187. config AUX
  188. bool
  189. select I2C
  190. diff --git a/hw/misc/meson.build b/hw/misc/meson.build
  191. index 892f8b91c5..3aea9a5e68 100644
  192. --- a/hw/misc/meson.build
  193. +++ b/hw/misc/meson.build
  194. @@ -115,6 +115,7 @@ system_ss.add(when: 'CONFIG_ARMSSE_CPUID', if_true: files('armsse-cpuid.c'))
  195. system_ss.add(when: 'CONFIG_ARMSSE_MHU', if_true: files('armsse-mhu.c'))
  196.  
  197. system_ss.add(when: 'CONFIG_PVPANIC_ISA', if_true: files('pvpanic-isa.c'))
  198. +system_ss.add(when: 'CONFIG_PVPANIC_MMIO', if_true: files('pvpanic-mmio.c'))
  199. system_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c'))
  200. system_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c'))
  201. system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files(
  202. diff --git a/hw/misc/pvpanic-mmio.c b/hw/misc/pvpanic-mmio.c
  203. new file mode 100644
  204. index 0000000000..aebe7227e6
  205. --- /dev/null
  206. +++ b/hw/misc/pvpanic-mmio.c
  207. @@ -0,0 +1,66 @@
  208. +/*
  209. + * QEMU simulated pvpanic device (MMIO frontend)
  210. + *
  211. + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  212. + *
  213. + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  214. + * See the COPYING file in the top-level directory.
  215. + */
  216. +
  217. +#include "qemu/osdep.h"
  218. +#include "qemu/module.h"
  219. +#include "sysemu/runstate.h"
  220. +
  221. +#include "hw/nvram/fw_cfg.h"
  222. +#include "hw/qdev-properties.h"
  223. +#include "hw/misc/pvpanic.h"
  224. +#include "qom/object.h"
  225. +#include "hw/isa/isa.h"
  226. +#include "standard-headers/linux/pvpanic.h"
  227. +
  228. +OBJECT_DECLARE_SIMPLE_TYPE(PVPanicMMIOState, PVPANIC_MMIO_DEVICE)
  229. +
  230. +#define PVPANIC_MMIO_SIZE 0x2
  231. +
  232. +struct PVPanicMMIOState {
  233. + SysBusDevice parent_obj;
  234. +
  235. + PVPanicState pvpanic;
  236. +};
  237. +
  238. +static void pvpanic_mmio_initfn(Object *obj)
  239. +{
  240. + PVPanicMMIOState *s = PVPANIC_MMIO_DEVICE(obj);
  241. +
  242. + pvpanic_setup_io(&s->pvpanic, DEVICE(s), PVPANIC_MMIO_SIZE);
  243. + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->pvpanic.mr);
  244. +}
  245. +
  246. +static Property pvpanic_mmio_properties[] = {
  247. + DEFINE_PROP_UINT8("events", PVPanicMMIOState, pvpanic.events,
  248. + PVPANIC_PANICKED | PVPANIC_CRASH_LOADED),
  249. + DEFINE_PROP_END_OF_LIST(),
  250. +};
  251. +
  252. +static void pvpanic_mmio_class_init(ObjectClass *klass, void *data)
  253. +{
  254. + DeviceClass *dc = DEVICE_CLASS(klass);
  255. +
  256. + device_class_set_props(dc, pvpanic_mmio_properties);
  257. + set_bit(DEVICE_CATEGORY_MISC, dc->categories);
  258. +}
  259. +
  260. +static const TypeInfo pvpanic_mmio_info = {
  261. + .name = TYPE_PVPANIC_MMIO_DEVICE,
  262. + .parent = TYPE_SYS_BUS_DEVICE,
  263. + .instance_size = sizeof(PVPanicMMIOState),
  264. + .instance_init = pvpanic_mmio_initfn,
  265. + .class_init = pvpanic_mmio_class_init,
  266. +};
  267. +
  268. +static void pvpanic_register_types(void)
  269. +{
  270. + type_register_static(&pvpanic_mmio_info);
  271. +}
  272. +
  273. +type_init(pvpanic_register_types)
  274. diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c
  275. index f8a68a6a6b..16a5676c4b 100644
  276. --- a/hw/openrisc/virt.c
  277. +++ b/hw/openrisc/virt.c
  278. @@ -318,7 +318,7 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
  279. {
  280. int pin, dev;
  281. uint32_t irq_map_stride = 0;
  282. - uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * 6] = {};
  283. + uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS * 6] = {};
  284. uint32_t *irq_map = full_irq_map;
  285.  
  286. /*
  287. @@ -330,11 +330,11 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
  288. * possible slot) seeing the interrupt-map-mask will allow the table
  289. * to wrap to any number of devices.
  290. */
  291. - for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
  292. + for (dev = 0; dev < PCI_NUM_PINS; dev++) {
  293. int devfn = dev << 3;
  294.  
  295. - for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
  296. - int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
  297. + for (pin = 0; pin < PCI_NUM_PINS; pin++) {
  298. + int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
  299. int i = 0;
  300.  
  301. /* Fill PCI address cells */
  302. @@ -357,7 +357,7 @@ static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base,
  303. }
  304.  
  305. qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map,
  306. - GPEX_NUM_IRQS * GPEX_NUM_IRQS *
  307. + PCI_NUM_PINS * PCI_NUM_PINS *
  308. irq_map_stride * sizeof(uint32_t));
  309.  
  310. qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask",
  311. @@ -409,7 +409,7 @@ static void openrisc_virt_pcie_init(OR1KVirtState *state,
  312. memory_region_add_subregion(get_system_memory(), pio_base, alias);
  313.  
  314. /* Connect IRQ lines. */
  315. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  316. + for (i = 0; i < PCI_NUM_PINS; i++) {
  317. pcie_irq = get_per_cpu_irq(cpus, num_cpus, irq_base + i);
  318.  
  319. sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pcie_irq);
  320. diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c
  321. index a6752fac5e..7d5d996f34 100644
  322. --- a/hw/pci-host/gpex.c
  323. +++ b/hw/pci-host/gpex.c
  324. @@ -32,6 +32,7 @@
  325. #include "qemu/osdep.h"
  326. #include "qapi/error.h"
  327. #include "hw/irq.h"
  328. +#include "hw/pci/pci_bus.h"
  329. #include "hw/pci-host/gpex.h"
  330. #include "hw/qdev-properties.h"
  331. #include "migration/vmstate.h"
  332. @@ -50,7 +51,7 @@ static void gpex_set_irq(void *opaque, int irq_num, int level)
  333.  
  334. int gpex_set_irq_num(GPEXHost *s, int index, int gsi)
  335. {
  336. - if (index >= GPEX_NUM_IRQS) {
  337. + if (index >= s->nr_irqs) {
  338. return -EINVAL;
  339. }
  340.  
  341. @@ -74,14 +75,29 @@ static PCIINTxRoute gpex_route_intx_pin_to_irq(void *opaque, int pin)
  342. return route;
  343. }
  344.  
  345. +static int gpex_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin)
  346. +{
  347. + PCIBus *bus = pci_device_root_bus(pci_dev);
  348. +
  349. + return (PCI_SLOT(pci_dev->devfn) + pin) % bus->nirq;
  350. +}
  351. +
  352. static void gpex_host_realize(DeviceState *dev, Error **errp)
  353. {
  354. PCIHostState *pci = PCI_HOST_BRIDGE(dev);
  355. GPEXHost *s = GPEX_HOST(dev);
  356. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  357. PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev);
  358. + pci_map_irq_fn map_irq_fn = pci_swizzle_map_irq_fn;
  359. int i;
  360.  
  361. + s->irq = g_malloc0(s->nr_irqs * sizeof(*s->irq));
  362. + s->irq_num = g_malloc0(s->nr_irqs * sizeof(*s->irq_num));
  363. +
  364. + if (s->nr_irqs != PCI_NUM_PINS) {
  365. + map_irq_fn = gpex_swizzle_map_irq_fn;
  366. + }
  367. +
  368. pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX);
  369. sysbus_init_mmio(sbd, &pex->mmio);
  370.  
  371. @@ -128,19 +144,27 @@ static void gpex_host_realize(DeviceState *dev, Error **errp)
  372. sysbus_init_mmio(sbd, &s->io_ioport);
  373. }
  374.  
  375. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  376. + for (i = 0; i < s->nr_irqs; i++) {
  377. sysbus_init_irq(sbd, &s->irq[i]);
  378. s->irq_num[i] = -1;
  379. }
  380.  
  381. - pci->bus = pci_register_root_bus(dev, "pcie.0", gpex_set_irq,
  382. - pci_swizzle_map_irq_fn, s, &s->io_mmio,
  383. - &s->io_ioport, 0, 4, TYPE_PCIE_BUS);
  384. + pci->bus = pci_register_root_bus(dev, "pcie.0", gpex_set_irq, map_irq_fn,
  385. + s, &s->io_mmio, &s->io_ioport, 0,
  386. + s->nr_irqs, TYPE_PCIE_BUS);
  387.  
  388. pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq);
  389. qdev_realize(DEVICE(&s->gpex_root), BUS(pci->bus), &error_fatal);
  390. }
  391.  
  392. +static void gpex_host_unrealize(DeviceState *dev)
  393. +{
  394. + GPEXHost *s = GPEX_HOST(dev);
  395. +
  396. + g_free(s->irq);
  397. + g_free(s->irq_num);
  398. +}
  399. +
  400. static const char *gpex_host_root_bus_path(PCIHostState *host_bridge,
  401. PCIBus *rootbus)
  402. {
  403. @@ -154,6 +178,7 @@ static Property gpex_host_properties[] = {
  404. */
  405. DEFINE_PROP_BOOL("allow-unmapped-accesses", GPEXHost,
  406. allow_unmapped_accesses, true),
  407. + DEFINE_PROP_UINT32("nr-irqs", GPEXHost, nr_irqs, PCI_NUM_PINS),
  408. DEFINE_PROP_END_OF_LIST(),
  409. };
  410.  
  411. @@ -164,6 +189,7 @@ static void gpex_host_class_init(ObjectClass *klass, void *data)
  412.  
  413. hc->root_bus_path = gpex_host_root_bus_path;
  414. dc->realize = gpex_host_realize;
  415. + dc->unrealize = gpex_host_unrealize;
  416. set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  417. dc->fw_name = "pci";
  418. device_class_set_props(dc, gpex_host_properties);
  419. diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
  420. index 99c4e6314b..c13e8c8142 100644
  421. --- a/hw/riscv/virt.c
  422. +++ b/hw/riscv/virt.c
  423. @@ -175,7 +175,7 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename,
  424. {
  425. int pin, dev;
  426. uint32_t irq_map_stride = 0;
  427. - uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS *
  428. + uint32_t full_irq_map[PCI_NUM_PINS * PCI_NUM_PINS *
  429. FDT_MAX_INT_MAP_WIDTH] = {};
  430. uint32_t *irq_map = full_irq_map;
  431.  
  432. @@ -187,11 +187,11 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename,
  433. * possible slot) seeing the interrupt-map-mask will allow the table
  434. * to wrap to any number of devices.
  435. */
  436. - for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
  437. + for (dev = 0; dev < PCI_NUM_PINS; dev++) {
  438. int devfn = dev * 0x8;
  439.  
  440. - for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
  441. - int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
  442. + for (pin = 0; pin < PCI_NUM_PINS; pin++) {
  443. + int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
  444. int i = 0;
  445.  
  446. /* Fill PCI address cells */
  447. @@ -217,7 +217,7 @@ static void create_pcie_irq_map(RISCVVirtState *s, void *fdt, char *nodename,
  448. }
  449.  
  450. qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map,
  451. - GPEX_NUM_IRQS * GPEX_NUM_IRQS *
  452. + PCI_NUM_PINS * PCI_NUM_PINS *
  453. irq_map_stride * sizeof(uint32_t));
  454.  
  455. qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask",
  456. @@ -1106,7 +1106,7 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
  457.  
  458. sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, pio_base);
  459.  
  460. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  461. + for (i = 0; i < PCI_NUM_PINS; i++) {
  462. irq = qdev_get_gpio_in(irqchip, PCIE_IRQ + i);
  463.  
  464. sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
  465. diff --git a/hw/virtio/virtio-blk-pci.c b/hw/virtio/virtio-blk-pci.c
  466. index 9743bee965..5fbf98f750 100644
  467. --- a/hw/virtio/virtio-blk-pci.c
  468. +++ b/hw/virtio/virtio-blk-pci.c
  469. @@ -62,6 +62,13 @@ static void virtio_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
  470. }
  471.  
  472. qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
  473. +
  474. + if (conf->x_apple_type) {
  475. + /* Apple virtio-blk uses a different vendor/device id */
  476. + pci_config_set_vendor_id(vpci_dev->pci_dev.config, PCI_VENDOR_ID_APPLE);
  477. + pci_config_set_device_id(vpci_dev->pci_dev.config,
  478. + PCI_DEVICE_ID_APPLE_VIRTIO_BLK);
  479. + }
  480. }
  481.  
  482. static void virtio_blk_pci_class_init(ObjectClass *klass, void *data)
  483. diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig
  484. new file mode 100644
  485. index 0000000000..7a2375dc95
  486. --- /dev/null
  487. +++ b/hw/vmapple/Kconfig
  488. @@ -0,0 +1,30 @@
  489. +config VMAPPLE_AES
  490. + bool
  491. +
  492. +config VMAPPLE_BDIF
  493. + bool
  494. +
  495. +config VMAPPLE_CFG
  496. + bool
  497. +
  498. +config VMAPPLE_PVG
  499. + bool
  500. +
  501. +config VMAPPLE
  502. + bool
  503. + depends on ARM && HVF
  504. + default y if ARM && HVF
  505. + imply PCI_DEVICES
  506. + select ARM_GIC
  507. + select PLATFORM_BUS
  508. + select PCI_EXPRESS
  509. + select PCI_EXPRESS_GENERIC_BRIDGE
  510. + select PL011 # UART
  511. + select PL031 # RTC
  512. + select PL061 # GPIO
  513. + select GPIO_PWR
  514. + select PVPANIC_MMIO
  515. + select VMAPPLE_AES
  516. + select VMAPPLE_BDIF
  517. + select VMAPPLE_CFG
  518. + select VMAPPLE_PVG
  519. diff --git a/hw/vmapple/aes.c b/hw/vmapple/aes.c
  520. new file mode 100644
  521. index 0000000000..eaf1e26abe
  522. --- /dev/null
  523. +++ b/hw/vmapple/aes.c
  524. @@ -0,0 +1,583 @@
  525. +/*
  526. + * QEMU Apple AES device emulation
  527. + *
  528. + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  529. + *
  530. + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  531. + * See the COPYING file in the top-level directory.
  532. + */
  533. +
  534. +#include "qemu/osdep.h"
  535. +#include "hw/irq.h"
  536. +#include "migration/vmstate.h"
  537. +#include "qemu/log.h"
  538. +#include "qemu/module.h"
  539. +#include "trace.h"
  540. +#include "hw/sysbus.h"
  541. +#include "crypto/hash.h"
  542. +#include "crypto/aes.h"
  543. +#include "crypto/cipher.h"
  544. +
  545. +#define TYPE_AES "apple-aes"
  546. +#define MAX_FIFO_SIZE 9
  547. +
  548. +#define CMD_KEY 0x1
  549. +#define CMD_KEY_CONTEXT_SHIFT 27
  550. +#define CMD_KEY_CONTEXT_MASK (0x1 << CMD_KEY_CONTEXT_SHIFT)
  551. +#define CMD_KEY_SELECT_SHIFT 24
  552. +#define CMD_KEY_SELECT_MASK (0x7 << CMD_KEY_SELECT_SHIFT)
  553. +#define CMD_KEY_KEY_LEN_SHIFT 22
  554. +#define CMD_KEY_KEY_LEN_MASK (0x3 << CMD_KEY_KEY_LEN_SHIFT)
  555. +#define CMD_KEY_ENCRYPT_SHIFT 20
  556. +#define CMD_KEY_ENCRYPT_MASK (0x1 << CMD_KEY_ENCRYPT_SHIFT)
  557. +#define CMD_KEY_BLOCK_MODE_SHIFT 16
  558. +#define CMD_KEY_BLOCK_MODE_MASK (0x3 << CMD_KEY_BLOCK_MODE_SHIFT)
  559. +#define CMD_IV 0x2
  560. +#define CMD_IV_CONTEXT_SHIFT 26
  561. +#define CMD_IV_CONTEXT_MASK (0x3 << CMD_KEY_CONTEXT_SHIFT)
  562. +#define CMD_DSB 0x3
  563. +#define CMD_SKG 0x4
  564. +#define CMD_DATA 0x5
  565. +#define CMD_DATA_KEY_CTX_SHIFT 27
  566. +#define CMD_DATA_KEY_CTX_MASK (0x1 << CMD_DATA_KEY_CTX_SHIFT)
  567. +#define CMD_DATA_IV_CTX_SHIFT 25
  568. +#define CMD_DATA_IV_CTX_MASK (0x3 << CMD_DATA_IV_CTX_SHIFT)
  569. +#define CMD_DATA_LEN_MASK 0xffffff
  570. +#define CMD_STORE_IV 0x6
  571. +#define CMD_STORE_IV_ADDR_MASK 0xffffff
  572. +#define CMD_WRITE_REG 0x7
  573. +#define CMD_FLAG 0x8
  574. +#define CMD_FLAG_STOP_MASK BIT(26)
  575. +#define CMD_FLAG_RAISE_IRQ_MASK BIT(27)
  576. +#define CMD_FLAG_INFO_MASK 0xff
  577. +#define CMD_MAX 0x10
  578. +
  579. +#define CMD_SHIFT 28
  580. +
  581. +#define REG_STATUS 0xc
  582. +#define REG_STATUS_DMA_READ_RUNNING BIT(0)
  583. +#define REG_STATUS_DMA_READ_PENDING BIT(1)
  584. +#define REG_STATUS_DMA_WRITE_RUNNING BIT(2)
  585. +#define REG_STATUS_DMA_WRITE_PENDING BIT(3)
  586. +#define REG_STATUS_BUSY BIT(4)
  587. +#define REG_STATUS_EXECUTING BIT(5)
  588. +#define REG_STATUS_READY BIT(6)
  589. +#define REG_STATUS_TEXT_DPA_SEEDED BIT(7)
  590. +#define REG_STATUS_UNWRAP_DPA_SEEDED BIT(8)
  591. +
  592. +#define REG_IRQ_STATUS 0x18
  593. +#define REG_IRQ_STATUS_INVALID_CMD BIT(2)
  594. +#define REG_IRQ_STATUS_FLAG BIT(5)
  595. +#define REG_IRQ_ENABLE 0x1c
  596. +#define REG_WATERMARK 0x20
  597. +#define REG_Q_STATUS 0x24
  598. +#define REG_FLAG_INFO 0x30
  599. +#define REG_FIFO 0x200
  600. +
  601. +static const uint32_t key_lens[4] = {
  602. + [0] = 16,
  603. + [1] = 24,
  604. + [2] = 32,
  605. + [3] = 64,
  606. +};
  607. +
  608. +struct key {
  609. + uint32_t key_len;
  610. + uint32_t key[8];
  611. +};
  612. +
  613. +struct iv {
  614. + uint32_t iv[4];
  615. +};
  616. +
  617. +struct context {
  618. + struct key key;
  619. + struct iv iv;
  620. +};
  621. +
  622. +static struct key builtin_keys[7] = {
  623. + [1] = {
  624. + .key_len = 32,
  625. + .key = { 0x1 },
  626. + },
  627. + [2] = {
  628. + .key_len = 32,
  629. + .key = { 0x2 },
  630. + },
  631. + [3] = {
  632. + .key_len = 32,
  633. + .key = { 0x3 },
  634. + }
  635. +};
  636. +
  637. +typedef struct AESState {
  638. + /* Private */
  639. + SysBusDevice parent_obj;
  640. +
  641. + /* Public */
  642. + qemu_irq irq;
  643. + MemoryRegion iomem1;
  644. + MemoryRegion iomem2;
  645. +
  646. + uint32_t status;
  647. + uint32_t q_status;
  648. + uint32_t irq_status;
  649. + uint32_t irq_enable;
  650. + uint32_t watermark;
  651. + uint32_t flag_info;
  652. + uint32_t fifo[MAX_FIFO_SIZE];
  653. + uint32_t fifo_idx;
  654. + struct key key[2];
  655. + struct iv iv[4];
  656. + bool is_encrypt;
  657. + QCryptoCipherMode block_mode;
  658. +} AESState;
  659. +
  660. +OBJECT_DECLARE_SIMPLE_TYPE(AESState, AES)
  661. +
  662. +static void aes_update_irq(AESState *s)
  663. +{
  664. + qemu_set_irq(s->irq, !!(s->irq_status & s->irq_enable));
  665. +}
  666. +
  667. +static uint64_t aes1_read(void *opaque, hwaddr offset, unsigned size)
  668. +{
  669. + AESState *s = opaque;
  670. + uint64_t res = 0;
  671. +
  672. + switch (offset) {
  673. + case REG_STATUS:
  674. + res = s->status;
  675. + break;
  676. + case REG_IRQ_STATUS:
  677. + res = s->irq_status;
  678. + break;
  679. + case REG_IRQ_ENABLE:
  680. + res = s->irq_enable;
  681. + break;
  682. + case REG_WATERMARK:
  683. + res = s->watermark;
  684. + break;
  685. + case REG_Q_STATUS:
  686. + res = s->q_status;
  687. + break;
  688. + case REG_FLAG_INFO:
  689. + res = s->flag_info;
  690. + break;
  691. +
  692. + default:
  693. + trace_aes_read_unknown(offset);
  694. + break;
  695. + }
  696. +
  697. + trace_aes_read(offset, res);
  698. +
  699. + return res;
  700. +}
  701. +
  702. +static void fifo_append(AESState *s, uint64_t val)
  703. +{
  704. + if (s->fifo_idx == MAX_FIFO_SIZE) {
  705. + /* Exceeded the FIFO. Bail out */
  706. + return;
  707. + }
  708. +
  709. + s->fifo[s->fifo_idx++] = val;
  710. +}
  711. +
  712. +static bool has_payload(AESState *s, uint32_t elems)
  713. +{
  714. + return s->fifo_idx >= (elems + 1);
  715. +}
  716. +
  717. +static bool cmd_key(AESState *s)
  718. +{
  719. + uint32_t cmd = s->fifo[0];
  720. + uint32_t key_select = (cmd & CMD_KEY_SELECT_MASK) >> CMD_KEY_SELECT_SHIFT;
  721. + uint32_t ctxt = (cmd & CMD_KEY_CONTEXT_MASK) >> CMD_KEY_CONTEXT_SHIFT;
  722. + uint32_t key_len;
  723. +
  724. + switch ((cmd & CMD_KEY_BLOCK_MODE_MASK) >> CMD_KEY_BLOCK_MODE_SHIFT) {
  725. + case 0:
  726. + s->block_mode = QCRYPTO_CIPHER_MODE_ECB;
  727. + break;
  728. + case 1:
  729. + s->block_mode = QCRYPTO_CIPHER_MODE_CBC;
  730. + break;
  731. + default:
  732. + return false;
  733. + }
  734. +
  735. + s->is_encrypt = !!((cmd & CMD_KEY_ENCRYPT_MASK) >> CMD_KEY_ENCRYPT_SHIFT);
  736. + key_len = key_lens[((cmd & CMD_KEY_KEY_LEN_MASK) >> CMD_KEY_KEY_LEN_SHIFT)];
  737. +
  738. + if (key_select) {
  739. + trace_aes_cmd_key_select_builtin(ctxt, key_select,
  740. + s->is_encrypt ? "en" : "de",
  741. + QCryptoCipherMode_str(s->block_mode));
  742. + s->key[ctxt] = builtin_keys[key_select];
  743. + } else {
  744. + trace_aes_cmd_key_select_new(ctxt, key_len,
  745. + s->is_encrypt ? "en" : "de",
  746. + QCryptoCipherMode_str(s->block_mode));
  747. + if (key_len > sizeof(s->key[ctxt].key)) {
  748. + return false;
  749. + }
  750. + if (!has_payload(s, key_len / sizeof(uint32_t))) {
  751. + /* wait for payload */
  752. + return false;
  753. + }
  754. + memcpy(&s->key[ctxt].key, &s->fifo[1], key_len);
  755. + s->key[ctxt].key_len = key_len;
  756. + }
  757. +
  758. + return true;
  759. +}
  760. +
  761. +static bool cmd_iv(AESState *s)
  762. +{
  763. + uint32_t cmd = s->fifo[0];
  764. + uint32_t ctxt = (cmd & CMD_IV_CONTEXT_MASK) >> CMD_IV_CONTEXT_SHIFT;
  765. +
  766. + if (!has_payload(s, 4)) {
  767. + /* wait for payload */
  768. + return false;
  769. + }
  770. + memcpy(&s->iv[ctxt].iv, &s->fifo[1], sizeof(s->iv[ctxt].iv));
  771. + trace_aes_cmd_iv(ctxt, s->fifo[1], s->fifo[2], s->fifo[3], s->fifo[4]);
  772. +
  773. + return true;
  774. +}
  775. +
  776. +static char hexdigit2str(uint8_t val)
  777. +{
  778. + g_assert(val < 0x10);
  779. + if (val >= 0xa) {
  780. + return 'a' + (val - 0xa);
  781. + } else {
  782. + return '0' + val;
  783. + }
  784. +}
  785. +
  786. +static void dump_data(const char *desc, const void *p, size_t len)
  787. +{
  788. + char hex[(len * 2) + 1];
  789. + const uint8_t *data = p;
  790. + char *hexp = hex;
  791. + size_t i;
  792. +
  793. + if (len > 0x1000) {
  794. + /* Too large buffer, let's bail out */
  795. + return;
  796. + }
  797. +
  798. + for (i = 0; i < len; i++) {
  799. + uint8_t val = data[i];
  800. + *(hexp++) = hexdigit2str(val >> 4);
  801. + *(hexp++) = hexdigit2str(val & 0xf);
  802. + }
  803. + *hexp = '\0';
  804. +
  805. + trace_aes_dump_data(desc, hex);
  806. +}
  807. +
  808. +static bool cmd_data(AESState *s)
  809. +{
  810. + uint32_t cmd = s->fifo[0];
  811. + uint32_t ctxt_iv = 0;
  812. + uint32_t ctxt_key = (cmd & CMD_DATA_KEY_CTX_MASK) >> CMD_DATA_KEY_CTX_SHIFT;
  813. + uint32_t len = cmd & CMD_DATA_LEN_MASK;
  814. + uint64_t src_addr = s->fifo[2];
  815. + uint64_t dst_addr = s->fifo[3];
  816. + QCryptoCipherAlgorithm alg;
  817. + QCryptoCipher *cipher;
  818. + char *src;
  819. + char *dst;
  820. +
  821. + src_addr |= ((uint64_t)s->fifo[1] << 16) & 0xffff00000000ULL;
  822. + dst_addr |= ((uint64_t)s->fifo[1] << 32) & 0xffff00000000ULL;
  823. +
  824. + trace_aes_cmd_data(ctxt_key, ctxt_iv, src_addr, dst_addr, len);
  825. +
  826. + if (!has_payload(s, 3)) {
  827. + /* wait for payload */
  828. + trace_aes_cmd_data_error("No payload");
  829. + return false;
  830. + }
  831. +
  832. + if (ctxt_key >= ARRAY_SIZE(s->key) ||
  833. + ctxt_iv >= ARRAY_SIZE(s->iv)) {
  834. + /* Invalid input */
  835. + trace_aes_cmd_data_error("Invalid key or iv");
  836. + return false;
  837. + }
  838. +
  839. + src = g_malloc0(len);
  840. + dst = g_malloc0(len);
  841. +
  842. + cpu_physical_memory_read(src_addr, src, len);
  843. +
  844. + dump_data("cmd_data(): src_data=", src, len);
  845. +
  846. + switch (s->key[ctxt_key].key_len) {
  847. + case 128 / 8:
  848. + alg = QCRYPTO_CIPHER_ALG_AES_128;
  849. + break;
  850. + case 192 / 8:
  851. + alg = QCRYPTO_CIPHER_ALG_AES_192;
  852. + break;
  853. + case 256 / 8:
  854. + alg = QCRYPTO_CIPHER_ALG_AES_256;
  855. + break;
  856. + default:
  857. + trace_aes_cmd_data_error("Invalid key len");
  858. + goto err_free;
  859. + }
  860. + cipher = qcrypto_cipher_new(alg, s->block_mode,
  861. + (void *)s->key[ctxt_key].key,
  862. + s->key[ctxt_key].key_len, NULL);
  863. + g_assert(cipher != NULL);
  864. + if (s->block_mode != QCRYPTO_CIPHER_MODE_ECB) {
  865. + if (qcrypto_cipher_setiv(cipher, (void *)s->iv[ctxt_iv].iv,
  866. + sizeof(s->iv[ctxt_iv].iv), NULL) != 0) {
  867. + trace_aes_cmd_data_error("Failed to set IV");
  868. + goto err_free_cipher;
  869. + }
  870. + }
  871. + if (s->is_encrypt) {
  872. + if (qcrypto_cipher_encrypt(cipher, src, dst, len, NULL) != 0) {
  873. + trace_aes_cmd_data_error("Encrypt failed");
  874. + goto err_free_cipher;
  875. + }
  876. + } else {
  877. + if (qcrypto_cipher_decrypt(cipher, src, dst, len, NULL) != 0) {
  878. + trace_aes_cmd_data_error("Decrypt failed");
  879. + goto err_free_cipher;
  880. + }
  881. + }
  882. + qcrypto_cipher_free(cipher);
  883. +
  884. + dump_data("cmd_data(): dst_data=", dst, len);
  885. + cpu_physical_memory_write(dst_addr, dst, len);
  886. + g_free(src);
  887. + g_free(dst);
  888. +
  889. + return true;
  890. +
  891. +err_free_cipher:
  892. + qcrypto_cipher_free(cipher);
  893. +err_free:
  894. + g_free(src);
  895. + g_free(dst);
  896. + return false;
  897. +}
  898. +
  899. +static bool cmd_store_iv(AESState *s)
  900. +{
  901. + uint32_t cmd = s->fifo[0];
  902. + uint32_t ctxt = (cmd & CMD_IV_CONTEXT_MASK) >> CMD_IV_CONTEXT_SHIFT;
  903. + uint64_t addr = s->fifo[1];
  904. +
  905. + if (!has_payload(s, 1)) {
  906. + /* wait for payload */
  907. + return false;
  908. + }
  909. +
  910. + if (ctxt >= ARRAY_SIZE(s->iv)) {
  911. + /* Invalid context selected */
  912. + return false;
  913. + }
  914. +
  915. + addr |= ((uint64_t)cmd << 32) & 0xff00000000ULL;
  916. + cpu_physical_memory_write(addr, &s->iv[ctxt].iv, sizeof(s->iv[ctxt].iv));
  917. +
  918. + trace_aes_cmd_store_iv(ctxt, addr, s->iv[ctxt].iv[0], s->iv[ctxt].iv[1],
  919. + s->iv[ctxt].iv[2], s->iv[ctxt].iv[3]);
  920. +
  921. + return true;
  922. +}
  923. +
  924. +static bool cmd_flag(AESState *s)
  925. +{
  926. + uint32_t cmd = s->fifo[0];
  927. + uint32_t raise_irq = cmd & CMD_FLAG_RAISE_IRQ_MASK;
  928. +
  929. + /* We always process data when it's coming in, so fire an IRQ immediately */
  930. + if (raise_irq) {
  931. + s->irq_status |= REG_IRQ_STATUS_FLAG;
  932. + }
  933. +
  934. + s->flag_info = cmd & CMD_FLAG_INFO_MASK;
  935. +
  936. + trace_aes_cmd_flag(!!raise_irq, s->flag_info);
  937. +
  938. + return true;
  939. +}
  940. +
  941. +static void fifo_process(AESState *s)
  942. +{
  943. + uint32_t cmd = s->fifo[0] >> CMD_SHIFT;
  944. + bool success = false;
  945. +
  946. + if (!s->fifo_idx) {
  947. + return;
  948. + }
  949. +
  950. + switch (cmd) {
  951. + case CMD_KEY:
  952. + success = cmd_key(s);
  953. + break;
  954. + case CMD_IV:
  955. + success = cmd_iv(s);
  956. + break;
  957. + case CMD_DATA:
  958. + success = cmd_data(s);
  959. + break;
  960. + case CMD_STORE_IV:
  961. + success = cmd_store_iv(s);
  962. + break;
  963. + case CMD_FLAG:
  964. + success = cmd_flag(s);
  965. + break;
  966. + default:
  967. + s->irq_status |= REG_IRQ_STATUS_INVALID_CMD;
  968. + break;
  969. + }
  970. +
  971. + if (success) {
  972. + s->fifo_idx = 0;
  973. + }
  974. +
  975. + trace_aes_fifo_process(cmd, success ? 1 : 0);
  976. +}
  977. +
  978. +static void aes1_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
  979. +{
  980. + AESState *s = opaque;
  981. +
  982. + trace_aes_write(offset, val);
  983. +
  984. + switch (offset) {
  985. + case REG_IRQ_STATUS:
  986. + s->irq_status &= ~val;
  987. + break;
  988. + case REG_IRQ_ENABLE:
  989. + s->irq_enable = val;
  990. + break;
  991. + case REG_FIFO:
  992. + fifo_append(s, val);
  993. + fifo_process(s);
  994. + break;
  995. + default:
  996. + trace_aes_write_unknown(offset);
  997. + return;
  998. + }
  999. +
  1000. + aes_update_irq(s);
  1001. +}
  1002. +
  1003. +static const MemoryRegionOps aes1_ops = {
  1004. + .read = aes1_read,
  1005. + .write = aes1_write,
  1006. + .endianness = DEVICE_NATIVE_ENDIAN,
  1007. + .valid = {
  1008. + .min_access_size = 4,
  1009. + .max_access_size = 8,
  1010. + },
  1011. + .impl = {
  1012. + .min_access_size = 4,
  1013. + .max_access_size = 4,
  1014. + },
  1015. +};
  1016. +
  1017. +static uint64_t aes2_read(void *opaque, hwaddr offset, unsigned size)
  1018. +{
  1019. + uint64_t res = 0;
  1020. +
  1021. + switch (offset) {
  1022. + case 0:
  1023. + res = 0;
  1024. + break;
  1025. + default:
  1026. + trace_aes_2_read_unknown(offset);
  1027. + break;
  1028. + }
  1029. +
  1030. + trace_aes_2_read(offset, res);
  1031. +
  1032. + return res;
  1033. +}
  1034. +
  1035. +static void aes2_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
  1036. +{
  1037. + trace_aes_2_write(offset, val);
  1038. +
  1039. + switch (offset) {
  1040. + default:
  1041. + trace_aes_2_write_unknown(offset);
  1042. + return;
  1043. + }
  1044. +}
  1045. +
  1046. +static const MemoryRegionOps aes2_ops = {
  1047. + .read = aes2_read,
  1048. + .write = aes2_write,
  1049. + .endianness = DEVICE_NATIVE_ENDIAN,
  1050. + .valid = {
  1051. + .min_access_size = 4,
  1052. + .max_access_size = 8,
  1053. + },
  1054. + .impl = {
  1055. + .min_access_size = 4,
  1056. + .max_access_size = 4,
  1057. + },
  1058. +};
  1059. +
  1060. +static void aes_reset(DeviceState *d)
  1061. +{
  1062. + AESState *s = AES(d);
  1063. +
  1064. + s->status = 0x3f80;
  1065. + s->q_status = 2;
  1066. + s->irq_status = 0;
  1067. + s->irq_enable = 0;
  1068. + s->watermark = 0;
  1069. +}
  1070. +
  1071. +static void aes_init(Object *obj)
  1072. +{
  1073. + AESState *s = AES(obj);
  1074. +
  1075. + memory_region_init_io(&s->iomem1, obj, &aes1_ops, s, TYPE_AES, 0x4000);
  1076. + memory_region_init_io(&s->iomem2, obj, &aes2_ops, s, TYPE_AES, 0x4000);
  1077. + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem1);
  1078. + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem2);
  1079. + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
  1080. +}
  1081. +
  1082. +static void aes_realize(DeviceState *dev, Error **errp)
  1083. +{
  1084. +}
  1085. +
  1086. +static void aes_class_init(ObjectClass *klass, void *data)
  1087. +{
  1088. + DeviceClass *dc = DEVICE_CLASS(klass);
  1089. +
  1090. + dc->reset = aes_reset;
  1091. + dc->realize = aes_realize;
  1092. +}
  1093. +
  1094. +static const TypeInfo aes_info = {
  1095. + .name = TYPE_AES,
  1096. + .parent = TYPE_SYS_BUS_DEVICE,
  1097. + .instance_size = sizeof(AESState),
  1098. + .class_init = aes_class_init,
  1099. + .instance_init = aes_init,
  1100. +};
  1101. +
  1102. +static void aes_register_types(void)
  1103. +{
  1104. + type_register_static(&aes_info);
  1105. +}
  1106. +
  1107. +type_init(aes_register_types)
  1108. diff --git a/hw/vmapple/apple-gfx.m b/hw/vmapple/apple-gfx.m
  1109. new file mode 100644
  1110. index 0000000000..173b721645
  1111. --- /dev/null
  1112. +++ b/hw/vmapple/apple-gfx.m
  1113. @@ -0,0 +1,579 @@
  1114. +/*
  1115. + * QEMU Apple ParavirtualizedGraphics.framework device
  1116. + *
  1117. + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  1118. + *
  1119. + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  1120. + * See the COPYING file in the top-level directory.
  1121. + *
  1122. + * ParavirtualizedGraphics.framework is a set of libraries that macOS provides
  1123. + * which implements 3d graphics passthrough to the host as well as a
  1124. + * proprietary guest communication channel to drive it. This device model
  1125. + * implements support to drive that library from within QEMU.
  1126. + */
  1127. +
  1128. +#include "qemu/osdep.h"
  1129. +#include "hw/irq.h"
  1130. +#include "migration/vmstate.h"
  1131. +#include "qemu/log.h"
  1132. +#include "qemu/module.h"
  1133. +#include "trace.h"
  1134. +#include "hw/sysbus.h"
  1135. +#include "hw/pci/msi.h"
  1136. +#include "crypto/hash.h"
  1137. +#include "sysemu/cpus.h"
  1138. +#include "ui/console.h"
  1139. +#include "monitor/monitor.h"
  1140. +#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
  1141. +#include <mach/mach.h>
  1142. +
  1143. +#define TYPE_APPLE_GFX "apple-gfx"
  1144. +
  1145. +#define MAX_MRS 512
  1146. +
  1147. +static const PGDisplayCoord_t apple_gfx_modes[] = {
  1148. + { .x = 1440, .y = 1080 },
  1149. + { .x = 1280, .y = 1024 },
  1150. +};
  1151. +
  1152. +/*
  1153. + * We have to map PVG memory into our address space. Use the one below
  1154. + * as base start address. In normal linker setups it points to a free
  1155. + * memory range.
  1156. + */
  1157. +#define APPLE_GFX_BASE_VA ((void *)(uintptr_t)0x500000000000UL)
  1158. +
  1159. +/*
  1160. + * ParavirtualizedGraphics.Framework only ships header files for the x86
  1161. + * variant which does not include IOSFC descriptors and host devices. We add
  1162. + * their definitions here so that we can also work with the ARM version.
  1163. + */
  1164. +typedef bool(^IOSFCRaiseInterrupt)(uint32_t vector);
  1165. +typedef bool(^IOSFCUnmapMemory)(void *a, void *b, void *c, void *d, void *e, void *f);
  1166. +typedef bool(^IOSFCMapMemory)(uint64_t phys, uint64_t len, bool ro, void **va, void *e, void *f);
  1167. +
  1168. +@interface PGDeviceDescriptorExt : PGDeviceDescriptor
  1169. +@property (readwrite, nonatomic) bool usingIOSurfaceMapper;
  1170. +@end
  1171. +
  1172. +@interface PGIOSurfaceHostDeviceDescriptor : NSObject
  1173. +-(PGIOSurfaceHostDeviceDescriptor *)init;
  1174. +@property (readwrite, nonatomic, copy, nullable) IOSFCMapMemory mapMemory;
  1175. +@property (readwrite, nonatomic, copy, nullable) IOSFCUnmapMemory unmapMemory;
  1176. +@property (readwrite, nonatomic, copy, nullable) IOSFCRaiseInterrupt raiseInterrupt;
  1177. +@end
  1178. +
  1179. +@interface PGIOSurfaceHostDevice : NSObject
  1180. +-(void)initWithDescriptor:(PGIOSurfaceHostDeviceDescriptor *) desc;
  1181. +-(uint32_t)mmioReadAtOffset:(size_t) offset;
  1182. +-(void)mmioWriteAtOffset:(size_t) offset value:(uint32_t)value;
  1183. +@end
  1184. +
  1185. +typedef struct AppleGFXMR {
  1186. + QTAILQ_ENTRY(AppleGFXMR) node;
  1187. + hwaddr pa;
  1188. + void *va;
  1189. + uint64_t len;
  1190. +} AppleGFXMR;
  1191. +
  1192. +typedef QTAILQ_HEAD(, AppleGFXMR) AppleGFXMRList;
  1193. +
  1194. +typedef struct AppleGFXTask {
  1195. + QTAILQ_ENTRY(AppleGFXTask) node;
  1196. + void *mem;
  1197. + uint64_t len;
  1198. +} AppleGFXTask;
  1199. +
  1200. +typedef QTAILQ_HEAD(, AppleGFXTask) AppleGFXTaskList;
  1201. +
  1202. +typedef struct AppleGFXState {
  1203. + /* Private */
  1204. + SysBusDevice parent_obj;
  1205. +
  1206. + /* Public */
  1207. + qemu_irq irq_gfx;
  1208. + qemu_irq irq_iosfc;
  1209. + MemoryRegion iomem_gfx;
  1210. + MemoryRegion iomem_iosfc;
  1211. + id<PGDevice> pgdev;
  1212. + id<PGDisplay> pgdisp;
  1213. + PGIOSurfaceHostDevice *pgiosfc;
  1214. + AppleGFXMRList mrs;
  1215. + AppleGFXTaskList tasks;
  1216. + QemuConsole *con;
  1217. + void *vram;
  1218. + id<MTLDevice> mtl;
  1219. + id<MTLTexture> texture;
  1220. + bool handles_frames;
  1221. + bool new_frame;
  1222. + bool cursor_show;
  1223. + DisplaySurface *surface;
  1224. + QEMUCursor *cursor;
  1225. +} AppleGFXState;
  1226. +
  1227. +
  1228. +OBJECT_DECLARE_SIMPLE_TYPE(AppleGFXState, APPLE_GFX)
  1229. +
  1230. +static AppleGFXTask *apple_gfx_new_task(AppleGFXState *s, uint64_t len)
  1231. +{
  1232. + void *base = APPLE_GFX_BASE_VA;
  1233. + AppleGFXTask *task;
  1234. +
  1235. + QTAILQ_FOREACH(task, &s->tasks, node) {
  1236. + if ((task->mem + task->len) > base) {
  1237. + base = task->mem + task->len;
  1238. + }
  1239. + }
  1240. +
  1241. + task = g_new0(AppleGFXTask, 1);
  1242. +
  1243. + task->len = len;
  1244. + task->mem = base;
  1245. + QTAILQ_INSERT_TAIL(&s->tasks, task, node);
  1246. +
  1247. + return task;
  1248. +}
  1249. +
  1250. +static AppleGFXMR *apple_gfx_mapMemory(AppleGFXState *s, AppleGFXTask *task,
  1251. + uint64_t voff, uint64_t phys, uint64_t len)
  1252. +{
  1253. + AppleGFXMR *mr = g_new0(AppleGFXMR, 1);
  1254. +
  1255. + mr->pa = phys;
  1256. + mr->len = len;
  1257. + mr->va = task->mem + voff;
  1258. + QTAILQ_INSERT_TAIL(&s->mrs, mr, node);
  1259. +
  1260. + return mr;
  1261. +}
  1262. +
  1263. +static uint64_t apple_gfx_read(void *opaque, hwaddr offset, unsigned size)
  1264. +{
  1265. + AppleGFXState *s = opaque;
  1266. + uint64_t res = 0;
  1267. +
  1268. + switch (offset) {
  1269. + default:
  1270. + res = [s->pgdev mmioReadAtOffset:offset];
  1271. + break;
  1272. + }
  1273. +
  1274. + trace_apple_gfx_read(offset, res);
  1275. +
  1276. + return res;
  1277. +}
  1278. +
  1279. +static void apple_gfx_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
  1280. +{
  1281. + AppleGFXState *s = opaque;
  1282. +
  1283. + trace_apple_gfx_write(offset, val);
  1284. +
  1285. + qemu_mutex_unlock_iothread();
  1286. + [s->pgdev mmioWriteAtOffset:offset value:val];
  1287. + qemu_mutex_lock_iothread();
  1288. +}
  1289. +
  1290. +static const MemoryRegionOps apple_gfx_ops = {
  1291. + .read = apple_gfx_read,
  1292. + .write = apple_gfx_write,
  1293. + .endianness = DEVICE_NATIVE_ENDIAN,
  1294. + .valid = {
  1295. + .min_access_size = 4,
  1296. + .max_access_size = 8,
  1297. + },
  1298. + .impl = {
  1299. + .min_access_size = 4,
  1300. + .max_access_size = 4,
  1301. + },
  1302. +};
  1303. +
  1304. +static uint64_t apple_iosfc_read(void *opaque, hwaddr offset, unsigned size)
  1305. +{
  1306. + AppleGFXState *s = opaque;
  1307. + uint64_t res = 0;
  1308. +
  1309. + qemu_mutex_unlock_iothread();
  1310. + res = [s->pgiosfc mmioReadAtOffset:offset];
  1311. + qemu_mutex_lock_iothread();
  1312. +
  1313. + trace_apple_iosfc_read(offset, res);
  1314. +
  1315. + return res;
  1316. +}
  1317. +
  1318. +static void apple_iosfc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
  1319. +{
  1320. + AppleGFXState *s = opaque;
  1321. +
  1322. + trace_apple_iosfc_write(offset, val);
  1323. +
  1324. + [s->pgiosfc mmioWriteAtOffset:offset value:val];
  1325. +}
  1326. +
  1327. +static const MemoryRegionOps apple_iosfc_ops = {
  1328. + .read = apple_iosfc_read,
  1329. + .write = apple_iosfc_write,
  1330. + .endianness = DEVICE_NATIVE_ENDIAN,
  1331. + .valid = {
  1332. + .min_access_size = 4,
  1333. + .max_access_size = 8,
  1334. + },
  1335. + .impl = {
  1336. + .min_access_size = 4,
  1337. + .max_access_size = 8,
  1338. + },
  1339. +};
  1340. +
  1341. +static void apple_gfx_fb_update_display(void *opaque)
  1342. +{
  1343. + AppleGFXState *s = opaque;
  1344. +
  1345. + if (!s->new_frame || !s->handles_frames) {
  1346. + return;
  1347. + }
  1348. +
  1349. + s->new_frame = false;
  1350. +
  1351. + BOOL r;
  1352. + uint32_t width = surface_width(s->surface);
  1353. + uint32_t height = surface_height(s->surface);
  1354. + MTLRegion region = MTLRegionMake2D(0, 0, width, height);
  1355. + id<MTLCommandQueue> commandQueue = [s->mtl newCommandQueue];
  1356. + id<MTLCommandBuffer> mipmapCommandBuffer = [commandQueue commandBuffer];
  1357. +
  1358. + r = [s->pgdisp encodeCurrentFrameToCommandBuffer:mipmapCommandBuffer
  1359. + texture:s->texture
  1360. + region:region];
  1361. +
  1362. + if (r != YES) {
  1363. + return;
  1364. + }
  1365. +
  1366. + id<MTLBlitCommandEncoder> blitCommandEncoder = [mipmapCommandBuffer blitCommandEncoder];
  1367. + [blitCommandEncoder generateMipmapsForTexture:s->texture];
  1368. + [blitCommandEncoder endEncoding];
  1369. + [mipmapCommandBuffer commit];
  1370. + [mipmapCommandBuffer waitUntilCompleted];
  1371. + [s->texture getBytes:s->vram bytesPerRow:(width * 4)
  1372. + bytesPerImage: (width * height * 4)
  1373. + fromRegion: region
  1374. + mipmapLevel: 0
  1375. + slice: 0];
  1376. +
  1377. + /* Need to render cursor manually if not supported by backend */
  1378. + if (!dpy_cursor_define_supported(s->con) && s->cursor && s->cursor_show) {
  1379. + pixman_image_t *image =
  1380. + pixman_image_create_bits(PIXMAN_a8r8g8b8,
  1381. + s->cursor->width,
  1382. + s->cursor->height,
  1383. + (uint32_t *)s->cursor->data,
  1384. + s->cursor->width * 4);
  1385. +
  1386. + pixman_image_composite(PIXMAN_OP_OVER,
  1387. + image, NULL, s->surface->image,
  1388. + 0, 0, 0, 0, s->pgdisp.cursorPosition.x,
  1389. + s->pgdisp.cursorPosition.y, s->cursor->width,
  1390. + s->cursor->height);
  1391. +
  1392. + pixman_image_unref(image);
  1393. + }
  1394. +
  1395. + dpy_gfx_update_full(s->con);
  1396. +
  1397. + [commandQueue release];
  1398. +}
  1399. +
  1400. +static const GraphicHwOps apple_gfx_fb_ops = {
  1401. + .gfx_update = apple_gfx_fb_update_display,
  1402. +};
  1403. +
  1404. +static void update_cursor(AppleGFXState *s)
  1405. +{
  1406. + dpy_mouse_set(s->con, s->pgdisp.cursorPosition.x, s->pgdisp.cursorPosition.y, s->cursor_show);
  1407. +
  1408. + /* Need to render manually if cursor is not natively supported */
  1409. + if (!dpy_cursor_define_supported(s->con)) {
  1410. + s->new_frame = true;
  1411. + }
  1412. +}
  1413. +
  1414. +static void set_mode(AppleGFXState *s, uint32_t width, uint32_t height)
  1415. +{
  1416. + void *vram = g_malloc0(width * height * 4);
  1417. + void *old_vram = s->vram;
  1418. + DisplaySurface *surface;
  1419. + MTLTextureDescriptor *textureDescriptor;
  1420. + id<MTLTexture> old_texture = s->texture;
  1421. +
  1422. + if (s->surface &&
  1423. + width == surface_width(s->surface) &&
  1424. + height == surface_height(s->surface)) {
  1425. + return;
  1426. + }
  1427. + surface = qemu_create_displaysurface_from(width, height, PIXMAN_LE_a8r8g8b8,
  1428. + width * 4, vram);
  1429. + s->surface = surface;
  1430. + dpy_gfx_replace_surface(s->con, surface);
  1431. + s->vram = vram;
  1432. + g_free(old_vram);
  1433. +
  1434. + textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
  1435. + width:width
  1436. + height:height
  1437. + mipmapped:NO];
  1438. + textureDescriptor.usage = s->pgdisp.minimumTextureUsage;
  1439. + s->texture = [s->mtl newTextureWithDescriptor:textureDescriptor];
  1440. +
  1441. + if (old_texture) {
  1442. + [old_texture release];
  1443. + }
  1444. +}
  1445. +
  1446. +static void create_fb(AppleGFXState *s)
  1447. +{
  1448. +
  1449. + s->con = graphic_console_init(NULL, 0, &apple_gfx_fb_ops, s);
  1450. + set_mode(s, 1440, 1080);
  1451. +
  1452. + s->cursor_show = true;
  1453. +}
  1454. +
  1455. +static void apple_gfx_reset(DeviceState *d)
  1456. +{
  1457. +}
  1458. +
  1459. +static void apple_gfx_init(Object *obj)
  1460. +{
  1461. + AppleGFXState *s = APPLE_GFX(obj);
  1462. +
  1463. + memory_region_init_io(&s->iomem_gfx, obj, &apple_gfx_ops, s, TYPE_APPLE_GFX, 0x4000);
  1464. + memory_region_init_io(&s->iomem_iosfc, obj, &apple_iosfc_ops, s, TYPE_APPLE_GFX, 0x10000);
  1465. + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem_gfx);
  1466. + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem_iosfc);
  1467. + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq_gfx);
  1468. + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq_iosfc);
  1469. +}
  1470. +
  1471. +static void apple_gfx_realize(DeviceState *dev, Error **errp)
  1472. +{
  1473. + AppleGFXState *s = APPLE_GFX(dev);
  1474. + PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
  1475. + PGDisplayDescriptor *disp_desc = [PGDisplayDescriptor new];
  1476. + PGIOSurfaceHostDeviceDescriptor *iosfc_desc = [PGIOSurfaceHostDeviceDescriptor new];
  1477. + PGDeviceDescriptorExt *desc_ext = (PGDeviceDescriptorExt *)desc;
  1478. + PGDisplayMode *modes[ARRAY_SIZE(apple_gfx_modes)];
  1479. + int i;
  1480. +
  1481. + for (i = 0; i < ARRAY_SIZE(apple_gfx_modes); i++) {
  1482. + modes[i] = [PGDisplayMode new];
  1483. + [modes[i] initWithSizeInPixels:apple_gfx_modes[i] refreshRateInHz:60.];
  1484. + }
  1485. +
  1486. + s->mtl = MTLCreateSystemDefaultDevice();
  1487. +
  1488. + desc.device = s->mtl;
  1489. + desc_ext.usingIOSurfaceMapper = true;
  1490. +
  1491. + desc.createTask = ^(uint64_t vmSize, void * _Nullable * _Nonnull baseAddress) {
  1492. + AppleGFXTask *task = apple_gfx_new_task(s, vmSize);
  1493. + *baseAddress = task->mem;
  1494. + trace_apple_gfx_create_task(vmSize, *baseAddress);
  1495. + return (PGTask_t *)task;
  1496. + };
  1497. +
  1498. + desc.destroyTask = ^(PGTask_t * _Nonnull _task) {
  1499. + AppleGFXTask *task = (AppleGFXTask *)_task;
  1500. + trace_apple_gfx_destroy_task(task);
  1501. + QTAILQ_REMOVE(&s->tasks, task, node);
  1502. + g_free(task);
  1503. + };
  1504. +
  1505. + desc.mapMemory = ^(PGTask_t * _Nonnull _task, uint32_t rangeCount, uint64_t virtualOffset, bool readOnly, PGPhysicalMemoryRange_t * _Nonnull ranges) {
  1506. + AppleGFXTask *task = (AppleGFXTask*)_task;
  1507. + mach_port_t mtask = mach_task_self();
  1508. + trace_apple_gfx_map_memory(task, rangeCount, virtualOffset, readOnly);
  1509. + for (int i = 0; i < rangeCount; i++) {
  1510. + PGPhysicalMemoryRange_t *range = &ranges[i];
  1511. + MemoryRegion *tmp_mr;
  1512. + /* TODO: Bounds checks? r/o? */
  1513. + qemu_mutex_lock_iothread();
  1514. + AppleGFXMR *mr = apple_gfx_mapMemory(s, task, virtualOffset,
  1515. + range->physicalAddress,
  1516. + range->physicalLength);
  1517. +
  1518. + trace_apple_gfx_map_memory_range(i, range->physicalAddress, range->physicalLength, mr->va);
  1519. +
  1520. + vm_address_t target = (vm_address_t)mr->va;
  1521. + uint64_t mask = 0;
  1522. + bool anywhere = false;
  1523. + vm_address_t source = (vm_address_t)gpa2hva(&tmp_mr, mr->pa, mr->len, NULL);
  1524. + vm_prot_t cur_protection = 0;
  1525. + vm_prot_t max_protection = 0;
  1526. + kern_return_t retval = vm_remap(mtask, &target, mr->len, mask,
  1527. + anywhere, mtask, source, false,
  1528. + &cur_protection, &max_protection,
  1529. + VM_INHERIT_DEFAULT);
  1530. + trace_apple_gfx_remap(retval, source, target);
  1531. + g_assert(retval == KERN_SUCCESS);
  1532. +
  1533. + qemu_mutex_unlock_iothread();
  1534. +
  1535. + virtualOffset += mr->len;
  1536. + }
  1537. + return (bool)true;
  1538. + };
  1539. +
  1540. + desc.unmapMemory = ^(PGTask_t * _Nonnull _task, uint64_t virtualOffset, uint64_t length) {
  1541. + AppleGFXTask *task = (AppleGFXTask *)_task;
  1542. + AppleGFXMR *mr, *next;
  1543. +
  1544. + trace_apple_gfx_unmap_memory(task, virtualOffset, length);
  1545. + qemu_mutex_lock_iothread();
  1546. + QTAILQ_FOREACH_SAFE(mr, &s->mrs, node, next) {
  1547. + if (mr->va >= (task->mem + virtualOffset) &&
  1548. + (mr->va + mr->len) <= (task->mem + virtualOffset + length)) {
  1549. + vm_address_t addr = (vm_address_t)mr->va;
  1550. + vm_deallocate(mach_task_self(), addr, mr->len);
  1551. + QTAILQ_REMOVE(&s->mrs, mr, node);
  1552. + g_free(mr);
  1553. + }
  1554. + }
  1555. + qemu_mutex_unlock_iothread();
  1556. + return (bool)true;
  1557. + };
  1558. +
  1559. + desc.readMemory = ^(uint64_t physicalAddress, uint64_t length, void * _Nonnull dst) {
  1560. + trace_apple_gfx_read_memory(physicalAddress, length, dst);
  1561. + cpu_physical_memory_read(physicalAddress, dst, length);
  1562. + return (bool)true;
  1563. + };
  1564. +
  1565. + desc.raiseInterrupt = ^(uint32_t vector) {
  1566. + bool locked;
  1567. +
  1568. + trace_apple_gfx_raise_irq(vector);
  1569. + locked = qemu_mutex_iothread_locked();
  1570. + if (!locked) {
  1571. + qemu_mutex_lock_iothread();
  1572. + }
  1573. + qemu_irq_pulse(s->irq_gfx);
  1574. + if (!locked) {
  1575. + qemu_mutex_unlock_iothread();
  1576. + }
  1577. + };
  1578. +
  1579. + desc.addTraceRange = ^(PGPhysicalMemoryRange_t * _Nonnull range, PGTraceRangeHandler _Nonnull handler) {
  1580. + /* Never saw this called. Return a bogus pointer so we catch access. */
  1581. + return (PGTraceRange_t *)(void *)(uintptr_t)0x4242;
  1582. + };
  1583. +
  1584. + desc.removeTraceRange = ^(PGTraceRange_t * _Nonnull range) {
  1585. + /* Never saw this called. Nothing to do. */
  1586. + };
  1587. + s->pgdev = PGNewDeviceWithDescriptor(desc);
  1588. +
  1589. + [disp_desc init];
  1590. + disp_desc.name = @"QEMU display";
  1591. + disp_desc.sizeInMillimeters = NSMakeSize(400., 300.); /* A 20" display */
  1592. + disp_desc.queue = dispatch_get_main_queue();
  1593. + disp_desc.newFrameEventHandler = ^(void) {
  1594. + trace_apple_gfx_new_frame();
  1595. +
  1596. + /* Tell QEMU gfx stack that a new frame arrived */
  1597. + s->handles_frames = true;
  1598. + s->new_frame = true;
  1599. + };
  1600. + disp_desc.modeChangeHandler = ^(PGDisplayCoord_t sizeInPixels, OSType pixelFormat) {
  1601. + trace_apple_gfx_mode_change(sizeInPixels.x, sizeInPixels.y);
  1602. + set_mode(s, sizeInPixels.x, sizeInPixels.y);
  1603. + };
  1604. + disp_desc.cursorGlyphHandler = ^(NSBitmapImageRep *glyph, PGDisplayCoord_t hotSpot) {
  1605. + uint32_t bpp = glyph.bitsPerPixel;
  1606. + uint64_t width = glyph.pixelsWide;
  1607. + uint64_t height = glyph.pixelsHigh;
  1608. +
  1609. + trace_apple_gfx_cursor_set(bpp, width, height);
  1610. +
  1611. + if (s->cursor) {
  1612. + cursor_unref(s->cursor);
  1613. + }
  1614. + s->cursor = cursor_alloc(width, height);
  1615. +
  1616. + /* TODO handle different bpp */
  1617. + if (bpp == 32) {
  1618. + memcpy(s->cursor->data, glyph.bitmapData, glyph.bytesPerPlane);
  1619. + dpy_cursor_define(s->con, s->cursor);
  1620. + update_cursor(s);
  1621. + }
  1622. + };
  1623. + disp_desc.cursorShowHandler = ^(BOOL show) {
  1624. + trace_apple_gfx_cursor_show(show);
  1625. + s->cursor_show = show;
  1626. + update_cursor(s);
  1627. + };
  1628. + disp_desc.cursorMoveHandler = ^(void) {
  1629. + trace_apple_gfx_cursor_move();
  1630. + update_cursor(s);
  1631. + };
  1632. +
  1633. + s->pgdisp = [s->pgdev newDisplayWithDescriptor:disp_desc port:0 serialNum:1234];
  1634. + s->pgdisp.modeList = [NSArray arrayWithObjects:modes count:ARRAY_SIZE(apple_gfx_modes)];
  1635. +
  1636. + [iosfc_desc init];
  1637. + iosfc_desc.mapMemory = ^(uint64_t phys, uint64_t len, bool ro, void **va, void *e, void *f) {
  1638. + trace_apple_iosfc_map_memory(phys, len, ro, va, e, f);
  1639. + MemoryRegion *tmp_mr;
  1640. + *va = gpa2hva(&tmp_mr, phys, len, NULL);
  1641. + return (bool)true;
  1642. + };
  1643. +
  1644. + iosfc_desc.unmapMemory = ^(void *a, void *b, void *c, void *d, void *e, void *f) {
  1645. + trace_apple_iosfc_unmap_memory(a, b, c, d, e, f);
  1646. + return (bool)true;
  1647. + };
  1648. +
  1649. + iosfc_desc.raiseInterrupt = ^(uint32_t vector) {
  1650. + trace_apple_iosfc_raise_irq(vector);
  1651. + bool locked = qemu_mutex_iothread_locked();
  1652. + if (!locked) {
  1653. + qemu_mutex_lock_iothread();
  1654. + }
  1655. + qemu_irq_pulse(s->irq_iosfc);
  1656. + if (!locked) {
  1657. + qemu_mutex_unlock_iothread();
  1658. + }
  1659. + return (bool)true;
  1660. + };
  1661. +
  1662. + s->pgiosfc = [PGIOSurfaceHostDevice new];
  1663. + [s->pgiosfc initWithDescriptor:iosfc_desc];
  1664. +
  1665. + QTAILQ_INIT(&s->mrs);
  1666. + QTAILQ_INIT(&s->tasks);
  1667. +
  1668. + create_fb(s);
  1669. +}
  1670. +
  1671. +static void apple_gfx_class_init(ObjectClass *klass, void *data)
  1672. +{
  1673. + DeviceClass *dc = DEVICE_CLASS(klass);
  1674. +
  1675. + dc->reset = apple_gfx_reset;
  1676. + dc->realize = apple_gfx_realize;
  1677. +}
  1678. +
  1679. +static TypeInfo apple_gfx_info = {
  1680. + .name = TYPE_APPLE_GFX,
  1681. + .parent = TYPE_SYS_BUS_DEVICE,
  1682. + .instance_size = sizeof(AppleGFXState),
  1683. + .class_init = apple_gfx_class_init,
  1684. + .instance_init = apple_gfx_init,
  1685. +};
  1686. +
  1687. +static void apple_gfx_register_types(void)
  1688. +{
  1689. + type_register_static(&apple_gfx_info);
  1690. +}
  1691. +
  1692. +type_init(apple_gfx_register_types)
  1693. diff --git a/hw/vmapple/bdif.c b/hw/vmapple/bdif.c
  1694. new file mode 100644
  1695. index 0000000000..36b5915ff3
  1696. --- /dev/null
  1697. +++ b/hw/vmapple/bdif.c
  1698. @@ -0,0 +1,245 @@
  1699. +/*
  1700. + * VMApple Backdoor Interface
  1701. + *
  1702. + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  1703. + *
  1704. + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  1705. + * See the COPYING file in the top-level directory.
  1706. + */
  1707. +
  1708. +#include "qemu/osdep.h"
  1709. +#include "hw/vmapple/bdif.h"
  1710. +#include "qemu/log.h"
  1711. +#include "qemu/module.h"
  1712. +#include "qapi/error.h"
  1713. +#include "trace.h"
  1714. +#include "hw/block/block.h"
  1715. +#include "sysemu/block-backend.h"
  1716. +
  1717. +#define REG_DEVID_MASK 0xffff0000
  1718. +#define DEVID_ROOT 0x00000000
  1719. +#define DEVID_AUX 0x00010000
  1720. +#define DEVID_USB 0x00100000
  1721. +
  1722. +#define REG_STATUS 0x0
  1723. +#define REG_STATUS_ACTIVE BIT(0)
  1724. +#define REG_CFG 0x4
  1725. +#define REG_CFG_ACTIVE BIT(1)
  1726. +#define REG_UNK1 0x8
  1727. +#define REG_BUSY 0x10
  1728. +#define REG_BUSY_READY BIT(0)
  1729. +#define REG_UNK2 0x400
  1730. +#define REG_CMD 0x408
  1731. +#define REG_NEXT_DEVICE 0x420
  1732. +#define REG_UNK3 0x434
  1733. +
  1734. +typedef struct vblk_sector {
  1735. + uint32_t pad;
  1736. + uint32_t pad2;
  1737. + uint32_t sector;
  1738. + uint32_t pad3;
  1739. +} VblkSector;
  1740. +
  1741. +typedef struct vblk_req_cmd {
  1742. + uint64_t addr;
  1743. + uint32_t len;
  1744. + uint32_t flags;
  1745. +} VblkReqCmd;
  1746. +
  1747. +typedef struct vblk_req {
  1748. + VblkReqCmd sector;
  1749. + VblkReqCmd data;
  1750. + VblkReqCmd retval;
  1751. +} VblkReq;
  1752. +
  1753. +#define VBLK_DATA_FLAGS_READ 0x00030001
  1754. +#define VBLK_DATA_FLAGS_WRITE 0x00010001
  1755. +
  1756. +#define VBLK_RET_SUCCESS 0
  1757. +#define VBLK_RET_FAILED 1
  1758. +
  1759. +static uint64_t bdif_read(void *opaque, hwaddr offset, unsigned size)
  1760. +{
  1761. + uint64_t ret = -1;
  1762. + uint64_t devid = (offset & REG_DEVID_MASK);
  1763. +
  1764. + switch (offset & ~REG_DEVID_MASK) {
  1765. + case REG_STATUS:
  1766. + ret = REG_STATUS_ACTIVE;
  1767. + break;
  1768. + case REG_CFG:
  1769. + ret = REG_CFG_ACTIVE;
  1770. + break;
  1771. + case REG_UNK1:
  1772. + ret = 0x420;
  1773. + break;
  1774. + case REG_BUSY:
  1775. + ret = REG_BUSY_READY;
  1776. + break;
  1777. + case REG_UNK2:
  1778. + ret = 0x1;
  1779. + break;
  1780. + case REG_UNK3:
  1781. + ret = 0x0;
  1782. + break;
  1783. + case REG_NEXT_DEVICE:
  1784. + switch (devid) {
  1785. + case DEVID_ROOT:
  1786. + ret = 0x8000000;
  1787. + break;
  1788. + case DEVID_AUX:
  1789. + ret = 0x10000;
  1790. + break;
  1791. + }
  1792. + break;
  1793. + }
  1794. +
  1795. + trace_bdif_read(offset, size, ret);
  1796. + return ret;
  1797. +}
  1798. +
  1799. +static void le2cpu_sector(VblkSector *sector)
  1800. +{
  1801. + sector->sector = le32_to_cpu(sector->sector);
  1802. +}
  1803. +
  1804. +static void le2cpu_reqcmd(VblkReqCmd *cmd)
  1805. +{
  1806. + cmd->addr = le64_to_cpu(cmd->addr);
  1807. + cmd->len = le32_to_cpu(cmd->len);
  1808. + cmd->flags = le32_to_cpu(cmd->flags);
  1809. +}
  1810. +
  1811. +static void le2cpu_req(VblkReq *req)
  1812. +{
  1813. + le2cpu_reqcmd(&req->sector);
  1814. + le2cpu_reqcmd(&req->data);
  1815. + le2cpu_reqcmd(&req->retval);
  1816. +}
  1817. +
  1818. +static void vblk_cmd(uint64_t devid, BlockBackend *blk, uint64_t value,
  1819. + uint64_t static_off)
  1820. +{
  1821. + VblkReq req;
  1822. + VblkSector sector;
  1823. + uint64_t off = 0;
  1824. + char *buf = NULL;
  1825. + uint8_t ret = VBLK_RET_FAILED;
  1826. + int r;
  1827. +
  1828. + cpu_physical_memory_read(value, &req, sizeof(req));
  1829. + le2cpu_req(&req);
  1830. +
  1831. + if (req.sector.len != sizeof(sector)) {
  1832. + ret = VBLK_RET_FAILED;
  1833. + goto out;
  1834. + }
  1835. +
  1836. + /* Read the vblk command */
  1837. + cpu_physical_memory_read(req.sector.addr, &sector, sizeof(sector));
  1838. + le2cpu_sector(&sector);
  1839. +
  1840. + off = sector.sector * 512ULL + static_off;
  1841. +
  1842. + /* Sanity check that we're not allocating bogus sizes */
  1843. + if (req.data.len > (128 * 1024 * 1024)) {
  1844. + goto out;
  1845. + }
  1846. +
  1847. + buf = g_malloc0(req.data.len);
  1848. + switch (req.data.flags) {
  1849. + case VBLK_DATA_FLAGS_READ:
  1850. + r = blk_pread(blk, off, req.data.len, buf, 0);
  1851. + trace_bdif_vblk_read(devid == DEVID_AUX ? "aux" : "root",
  1852. + req.data.addr, off, req.data.len, r);
  1853. + if (r < 0) {
  1854. + goto out;
  1855. + }
  1856. + cpu_physical_memory_write(req.data.addr, buf, req.data.len);
  1857. + ret = VBLK_RET_SUCCESS;
  1858. + break;
  1859. + case VBLK_DATA_FLAGS_WRITE:
  1860. + /* Not needed, iBoot only reads */
  1861. + break;
  1862. + default:
  1863. + break;
  1864. + }
  1865. +
  1866. +out:
  1867. + g_free(buf);
  1868. + cpu_physical_memory_write(req.retval.addr, &ret, 1);
  1869. +}
  1870. +
  1871. +static void bdif_write(void *opaque, hwaddr offset,
  1872. + uint64_t value, unsigned size)
  1873. +{
  1874. + VMAppleBdifState *s = opaque;
  1875. + uint64_t devid = (offset & REG_DEVID_MASK);
  1876. +
  1877. + trace_bdif_write(offset, size, value);
  1878. +
  1879. + switch (offset & ~REG_DEVID_MASK) {
  1880. + case REG_CMD:
  1881. + switch (devid) {
  1882. + case DEVID_ROOT:
  1883. + vblk_cmd(devid, s->root, value, 0x0);
  1884. + break;
  1885. + case DEVID_AUX:
  1886. + vblk_cmd(devid, s->aux, value, 0x0);
  1887. + break;
  1888. + }
  1889. + break;
  1890. + }
  1891. +}
  1892. +
  1893. +static const MemoryRegionOps bdif_ops = {
  1894. + .read = bdif_read,
  1895. + .write = bdif_write,
  1896. + .endianness = DEVICE_NATIVE_ENDIAN,
  1897. + .valid = {
  1898. + .min_access_size = 1,
  1899. + .max_access_size = 8,
  1900. + },
  1901. + .impl = {
  1902. + .min_access_size = 1,
  1903. + .max_access_size = 8,
  1904. + },
  1905. +};
  1906. +
  1907. +static void bdif_init(Object *obj)
  1908. +{
  1909. + VMAppleBdifState *s = VMAPPLE_BDIF(obj);
  1910. +
  1911. + memory_region_init_io(&s->mmio, obj, &bdif_ops, obj,
  1912. + "VMApple Backdoor Interface", VMAPPLE_BDIF_SIZE);
  1913. + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
  1914. +}
  1915. +
  1916. +static Property bdif_properties[] = {
  1917. + DEFINE_PROP_DRIVE("aux", VMAppleBdifState, aux),
  1918. + DEFINE_PROP_DRIVE("root", VMAppleBdifState, root),
  1919. + DEFINE_PROP_END_OF_LIST(),
  1920. +};
  1921. +
  1922. +static void bdif_class_init(ObjectClass *klass, void *data)
  1923. +{
  1924. + DeviceClass *dc = DEVICE_CLASS(klass);
  1925. +
  1926. + dc->desc = "VMApple Backdoor Interface";
  1927. + device_class_set_props(dc, bdif_properties);
  1928. +}
  1929. +
  1930. +static const TypeInfo bdif_info = {
  1931. + .name = TYPE_VMAPPLE_BDIF,
  1932. + .parent = TYPE_SYS_BUS_DEVICE,
  1933. + .instance_size = sizeof(VMAppleBdifState),
  1934. + .instance_init = bdif_init,
  1935. + .class_init = bdif_class_init,
  1936. +};
  1937. +
  1938. +static void bdif_register_types(void)
  1939. +{
  1940. + type_register_static(&bdif_info);
  1941. +}
  1942. +
  1943. +type_init(bdif_register_types)
  1944. diff --git a/hw/vmapple/cfg.c b/hw/vmapple/cfg.c
  1945. new file mode 100644
  1946. index 0000000000..d48e3c3afa
  1947. --- /dev/null
  1948. +++ b/hw/vmapple/cfg.c
  1949. @@ -0,0 +1,105 @@
  1950. +/*
  1951. + * VMApple Configuration Region
  1952. + *
  1953. + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  1954. + *
  1955. + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  1956. + * See the COPYING file in the top-level directory.
  1957. + */
  1958. +
  1959. +#include "qemu/osdep.h"
  1960. +#include "hw/vmapple/cfg.h"
  1961. +#include "qemu/log.h"
  1962. +#include "qemu/module.h"
  1963. +#include "qapi/error.h"
  1964. +
  1965. +static void vmapple_cfg_reset(DeviceState *dev)
  1966. +{
  1967. + VMAppleCfgState *s = VMAPPLE_CFG(dev);
  1968. + VMAppleCfg *cfg;
  1969. +
  1970. + cfg = memory_region_get_ram_ptr(&s->mem);
  1971. + memset((void *)cfg, 0, VMAPPLE_CFG_SIZE);
  1972. + *cfg = s->cfg;
  1973. +}
  1974. +
  1975. +static void vmapple_cfg_realize(DeviceState *dev, Error **errp)
  1976. +{
  1977. + VMAppleCfgState *s = VMAPPLE_CFG(dev);
  1978. + uint32_t i;
  1979. +
  1980. + strncpy(s->cfg.serial, s->serial, sizeof(s->cfg.serial));
  1981. + strncpy(s->cfg.model, s->model, sizeof(s->cfg.model));
  1982. + strncpy(s->cfg.soc_name, s->soc_name, sizeof(s->cfg.soc_name));
  1983. + strncpy(s->cfg.unk8, "D/A", sizeof(s->cfg.soc_name));
  1984. + s->cfg.ecid = cpu_to_be64(s->cfg.ecid);
  1985. + s->cfg.version = 2;
  1986. + s->cfg.unk1 = 1;
  1987. + s->cfg.unk2 = 1;
  1988. + s->cfg.unk3 = 0x20;
  1989. + s->cfg.unk4 = 0;
  1990. + s->cfg.unk5 = 1;
  1991. + s->cfg.unk6 = 1;
  1992. + s->cfg.unk7 = 0;
  1993. + s->cfg.unk10 = 1;
  1994. +
  1995. + g_assert(s->cfg.nr_cpus < ARRAY_SIZE(s->cfg.cpu_ids));
  1996. + for (i = 0; i < s->cfg.nr_cpus; i++) {
  1997. + s->cfg.cpu_ids[i] = i;
  1998. + }
  1999. +}
  2000. +
  2001. +static void vmapple_cfg_init(Object *obj)
  2002. +{
  2003. + VMAppleCfgState *s = VMAPPLE_CFG(obj);
  2004. +
  2005. + memory_region_init_ram(&s->mem, obj, "VMApple Config", VMAPPLE_CFG_SIZE,
  2006. + &error_fatal);
  2007. + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mem);
  2008. +
  2009. + s->serial = (char *)"1234";
  2010. + s->model = (char *)"VM0001";
  2011. + s->soc_name = (char *)"Apple M1 (Virtual)";
  2012. +}
  2013. +
  2014. +static Property vmapple_cfg_properties[] = {
  2015. + DEFINE_PROP_UINT32("nr-cpus", VMAppleCfgState, cfg.nr_cpus, 1),
  2016. + DEFINE_PROP_UINT64("ecid", VMAppleCfgState, cfg.ecid, 0),
  2017. + DEFINE_PROP_UINT64("ram-size", VMAppleCfgState, cfg.ram_size, 0),
  2018. + DEFINE_PROP_UINT32("run_installer1", VMAppleCfgState, cfg.run_installer1, 0),
  2019. + DEFINE_PROP_UINT32("run_installer2", VMAppleCfgState, cfg.run_installer2, 0),
  2020. + DEFINE_PROP_UINT32("rnd", VMAppleCfgState, cfg.rnd, 0),
  2021. + DEFINE_PROP_MACADDR("mac-en0", VMAppleCfgState, cfg.mac_en0),
  2022. + DEFINE_PROP_MACADDR("mac-en1", VMAppleCfgState, cfg.mac_en1),
  2023. + DEFINE_PROP_MACADDR("mac-wifi0", VMAppleCfgState, cfg.mac_wifi0),
  2024. + DEFINE_PROP_MACADDR("mac-bt0", VMAppleCfgState, cfg.mac_bt0),
  2025. + DEFINE_PROP_STRING("serial", VMAppleCfgState, serial),
  2026. + DEFINE_PROP_STRING("model", VMAppleCfgState, model),
  2027. + DEFINE_PROP_STRING("soc_name", VMAppleCfgState, soc_name),
  2028. + DEFINE_PROP_END_OF_LIST(),
  2029. +};
  2030. +
  2031. +static void vmapple_cfg_class_init(ObjectClass *klass, void *data)
  2032. +{
  2033. + DeviceClass *dc = DEVICE_CLASS(klass);
  2034. +
  2035. + dc->realize = vmapple_cfg_realize;
  2036. + dc->desc = "VMApple Configuration Region";
  2037. + device_class_set_props(dc, vmapple_cfg_properties);
  2038. + dc->reset = vmapple_cfg_reset;
  2039. +}
  2040. +
  2041. +static const TypeInfo vmapple_cfg_info = {
  2042. + .name = TYPE_VMAPPLE_CFG,
  2043. + .parent = TYPE_SYS_BUS_DEVICE,
  2044. + .instance_size = sizeof(VMAppleCfgState),
  2045. + .instance_init = vmapple_cfg_init,
  2046. + .class_init = vmapple_cfg_class_init,
  2047. +};
  2048. +
  2049. +static void vmapple_cfg_register_types(void)
  2050. +{
  2051. + type_register_static(&vmapple_cfg_info);
  2052. +}
  2053. +
  2054. +type_init(vmapple_cfg_register_types)
  2055. diff --git a/hw/vmapple/meson.build b/hw/vmapple/meson.build
  2056. new file mode 100644
  2057. index 0000000000..76d745f6b8
  2058. --- /dev/null
  2059. +++ b/hw/vmapple/meson.build
  2060. @@ -0,0 +1,5 @@
  2061. +system_ss.add(when: 'CONFIG_VMAPPLE_AES', if_true: files('aes.c'))
  2062. +system_ss.add(when: 'CONFIG_VMAPPLE_BDIF', if_true: files('bdif.c'))
  2063. +system_ss.add(when: 'CONFIG_VMAPPLE_CFG', if_true: files('cfg.c'))
  2064. +system_ss.add(when: 'CONFIG_VMAPPLE_PVG', if_true: [files('apple-gfx.m'), pvg, metal])
  2065. +specific_ss.add(when: 'CONFIG_VMAPPLE', if_true: files('vmapple.c'))
  2066. diff --git a/hw/vmapple/trace-events b/hw/vmapple/trace-events
  2067. new file mode 100644
  2068. index 0000000000..078e679560
  2069. --- /dev/null
  2070. +++ b/hw/vmapple/trace-events
  2071. @@ -0,0 +1,47 @@
  2072. +# See docs/devel/tracing.rst for syntax documentation.
  2073. +
  2074. +# aes.c
  2075. +aes_read_unknown(uint64_t offset) "offset=0x%"PRIx64
  2076. +aes_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
  2077. +aes_cmd_key_select_builtin(uint32_t ctx, uint32_t key_id, const char *direction, const char *cipher) "[%d] Selecting builtin key %d to %scrypt with %s"
  2078. +aes_cmd_key_select_new(uint32_t ctx, uint32_t key_len, const char *direction, const char *cipher) "[%d] Selecting new key size=%d to %scrypt with %s"
  2079. +aes_cmd_iv(uint32_t ctx, uint32_t iv0, uint32_t iv1, uint32_t iv2, uint32_t iv3) "[%d] 0x%08x 0x%08x 0x%08x 0x%08x"
  2080. +aes_cmd_data(uint32_t key, uint32_t iv, uint64_t src, uint64_t dst, uint32_t len) "[key=%d iv=%d] src=0x%"PRIx64" dst=0x%"PRIx64" len=0x%x"
  2081. +aes_cmd_data_error(const char *reason) "reason=%s"
  2082. +aes_cmd_store_iv(uint32_t ctx, uint64_t addr, uint32_t iv0, uint32_t iv1, uint32_t iv2, uint32_t iv3) "[%d] addr=0x%"PRIx64"x -> 0x%08x 0x%08x 0x%08x 0x%08x"
  2083. +aes_cmd_flag(uint32_t raise, uint32_t flag_info) "raise=%d flag_info=0x%x"
  2084. +aes_fifo_process(uint32_t cmd, uint32_t success) "cmd=%d success=%d"
  2085. +aes_write_unknown(uint64_t offset) "offset=0x%"PRIx64
  2086. +aes_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64
  2087. +aes_2_read_unknown(uint64_t offset) "offset=0x%"PRIx64
  2088. +aes_2_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
  2089. +aes_2_write_unknown(uint64_t offset) "offset=0x%"PRIx64
  2090. +aes_2_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64
  2091. +aes_dump_data(const char *desc, const char *hex) "%s%s"
  2092. +
  2093. +# bdif.c
  2094. +bdif_read(uint64_t offset, uint32_t size, uint64_t value) "offset=0x%"PRIx64" size=0x%x value=0x%"PRIx64
  2095. +bdif_write(uint64_t offset, uint32_t size, uint64_t value) "offset=0x%"PRIx64" size=0x%x value=0x%"PRIx64
  2096. +bdif_vblk_read(const char *dev, uint64_t addr, uint64_t offset, uint32_t len, int r) "dev=%s addr=0x%"PRIx64" off=0x%"PRIx64" size=0x%x r=%d"
  2097. +
  2098. +# apple-gfx.m
  2099. +apple_gfx_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
  2100. +apple_gfx_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64
  2101. +apple_gfx_create_task(uint32_t vm_size, void *va) "vm_size=0x%x base_addr=%p"
  2102. +apple_gfx_destroy_task(void *task) "task=%p"
  2103. +apple_gfx_map_memory(void *task, uint32_t range_count, uint64_t virtual_offset, uint32_t read_only) "task=%p range_count=0x%x virtual_offset=0x%"PRIx64" read_only=%d"
  2104. +apple_gfx_map_memory_range(uint32_t i, uint64_t phys_addr, uint64_t phys_len, void *va) "[%d] phys_addr=0x%"PRIx64" phys_len=0x%"PRIx64" va=%p"
  2105. +apple_gfx_remap(uint64_t retval, uint64_t source, uint64_t target) "retval=%"PRId64" source=0x%"PRIx64" target=0x%"PRIx64
  2106. +apple_gfx_unmap_memory(void *task, uint64_t virtual_offset, uint64_t length) "task=%p virtual_offset=0x%"PRIx64" length=0x%"PRIx64
  2107. +apple_gfx_read_memory(uint64_t phys_address, uint64_t length, void *dst) "phys_addr=0x%"PRIx64" length=0x%"PRIx64" dest=%p"
  2108. +apple_gfx_raise_irq(uint32_t vector) "vector=0x%x"
  2109. +apple_gfx_new_frame(void) ""
  2110. +apple_gfx_mode_change(uint64_t x, uint64_t y) "x=%"PRId64" y=%"PRId64
  2111. +apple_gfx_cursor_set(uint32_t bpp, uint64_t width, uint64_t height) "bpp=%d width=%"PRId64" height=0x%"PRId64
  2112. +apple_gfx_cursor_show(uint32_t show) "show=%d"
  2113. +apple_gfx_cursor_move(void) ""
  2114. +apple_iosfc_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
  2115. +apple_iosfc_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64
  2116. +apple_iosfc_map_memory(uint64_t phys, uint64_t len, uint32_t ro, void *va, void *e, void *f) "phys=0x%"PRIx64" len=0x%"PRIx64" ro=%d va=%p e=%p f=%p"
  2117. +apple_iosfc_unmap_memory(void *a, void *b, void *c, void *d, void *e, void *f) "a=%p b=%p c=%p d=%p e=%p f=%p"
  2118. +apple_iosfc_raise_irq(uint32_t vector) "vector=0x%x"
  2119. diff --git a/hw/vmapple/trace.h b/hw/vmapple/trace.h
  2120. new file mode 100644
  2121. index 0000000000..572adbefe0
  2122. --- /dev/null
  2123. +++ b/hw/vmapple/trace.h
  2124. @@ -0,0 +1 @@
  2125. +#include "trace/trace-hw_vmapple.h"
  2126. diff --git a/hw/vmapple/vmapple.c b/hw/vmapple/vmapple.c
  2127. new file mode 100644
  2128. index 0000000000..5d3fe54b96
  2129. --- /dev/null
  2130. +++ b/hw/vmapple/vmapple.c
  2131. @@ -0,0 +1,661 @@
  2132. +/*
  2133. + * VMApple machine emulation
  2134. + *
  2135. + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  2136. + *
  2137. + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  2138. + * See the COPYING file in the top-level directory.
  2139. + *
  2140. + * VMApple is the device model that the macOS built-in hypervisor called
  2141. + * "Virtualization.framework" exposes to Apple Silicon macOS guests. The
  2142. + * machine model in this file implements the same device model in QEMU, but
  2143. + * does not use any code from Virtualization.Framework.
  2144. + */
  2145. +
  2146. +#include "qemu/osdep.h"
  2147. +#include "qemu/help-texts.h"
  2148. +#include "qemu/datadir.h"
  2149. +#include "qemu/units.h"
  2150. +#include "qemu/option.h"
  2151. +#include "monitor/qdev.h"
  2152. +#include "qapi/error.h"
  2153. +#include "hw/sysbus.h"
  2154. +#include "hw/arm/boot.h"
  2155. +#include "hw/arm/primecell.h"
  2156. +#include "hw/boards.h"
  2157. +#include "net/net.h"
  2158. +#include "sysemu/sysemu.h"
  2159. +#include "sysemu/runstate.h"
  2160. +#include "sysemu/kvm.h"
  2161. +#include "sysemu/hvf.h"
  2162. +#include "hw/loader.h"
  2163. +#include "qapi/error.h"
  2164. +#include "qemu/bitops.h"
  2165. +#include "qemu/error-report.h"
  2166. +#include "qemu/module.h"
  2167. +#include "hw/pci-host/gpex.h"
  2168. +#include "hw/virtio/virtio-pci.h"
  2169. +#include "hw/qdev-properties.h"
  2170. +#include "hw/intc/arm_gic.h"
  2171. +#include "hw/intc/arm_gicv3_common.h"
  2172. +#include "hw/irq.h"
  2173. +#include "qapi/visitor.h"
  2174. +#include "qapi/qapi-visit-common.h"
  2175. +#include "standard-headers/linux/input.h"
  2176. +#include "target/arm/internals.h"
  2177. +#include "target/arm/kvm_arm.h"
  2178. +#include "hw/char/pl011.h"
  2179. +#include "qemu/guest-random.h"
  2180. +#include "sysemu/reset.h"
  2181. +#include "qemu/log.h"
  2182. +#include "hw/vmapple/cfg.h"
  2183. +#include "hw/misc/pvpanic.h"
  2184. +#include "hw/vmapple/bdif.h"
  2185. +
  2186. +struct VMAppleMachineClass {
  2187. + MachineClass parent;
  2188. +};
  2189. +
  2190. +struct VMAppleMachineState {
  2191. + MachineState parent;
  2192. + Notifier machine_done;
  2193. + struct arm_boot_info bootinfo;
  2194. + MemMapEntry *memmap;
  2195. + const int *irqmap;
  2196. + DeviceState *gic;
  2197. + DeviceState *cfg;
  2198. + Notifier powerdown_notifier;
  2199. + PCIBus *bus;
  2200. + MemoryRegion fw_mr;
  2201. + uint64_t uuid;
  2202. +};
  2203. +
  2204. +#define DEFINE_VMAPPLE_MACHINE_LATEST(major, minor, latest) \
  2205. + static void vmapple##major##_##minor##_class_init(ObjectClass *oc, \
  2206. + void *data) \
  2207. + { \
  2208. + MachineClass *mc = MACHINE_CLASS(oc); \
  2209. + vmapple_machine_##major##_##minor##_options(mc); \
  2210. + mc->desc = "QEMU " # major "." # minor " Apple Virtual Machine"; \
  2211. + if (latest) { \
  2212. + mc->alias = "vmapple"; \
  2213. + } \
  2214. + } \
  2215. + static const TypeInfo machvmapple##major##_##minor##_info = { \
  2216. + .name = MACHINE_TYPE_NAME("vmapple-" # major "." # minor), \
  2217. + .parent = TYPE_VMAPPLE_MACHINE, \
  2218. + .class_init = vmapple##major##_##minor##_class_init, \
  2219. + }; \
  2220. + static void machvmapple_machine_##major##_##minor##_init(void) \
  2221. + { \
  2222. + type_register_static(&machvmapple##major##_##minor##_info); \
  2223. + } \
  2224. + type_init(machvmapple_machine_##major##_##minor##_init);
  2225. +
  2226. +#define DEFINE_VMAPPLE_MACHINE_AS_LATEST(major, minor) \
  2227. + DEFINE_VMAPPLE_MACHINE_LATEST(major, minor, true)
  2228. +#define DEFINE_VMAPPLE_MACHINE(major, minor) \
  2229. + DEFINE_VMAPPLE_MACHINE_LATEST(major, minor, false)
  2230. +
  2231. +#define TYPE_VMAPPLE_MACHINE MACHINE_TYPE_NAME("vmapple")
  2232. +OBJECT_DECLARE_TYPE(VMAppleMachineState, VMAppleMachineClass, VMAPPLE_MACHINE)
  2233. +
  2234. +/* Number of external interrupt lines to configure the GIC with */
  2235. +#define NUM_IRQS 256
  2236. +
  2237. +enum {
  2238. + VMAPPLE_FIRMWARE,
  2239. + VMAPPLE_CONFIG,
  2240. + VMAPPLE_MEM,
  2241. + VMAPPLE_GIC_DIST,
  2242. + VMAPPLE_GIC_REDIST,
  2243. + VMAPPLE_UART,
  2244. + VMAPPLE_RTC,
  2245. + VMAPPLE_PCIE,
  2246. + VMAPPLE_PCIE_MMIO,
  2247. + VMAPPLE_PCIE_ECAM,
  2248. + VMAPPLE_GPIO,
  2249. + VMAPPLE_PVPANIC,
  2250. + VMAPPLE_APV_GFX,
  2251. + VMAPPLE_APV_IOSFC,
  2252. + VMAPPLE_AES_1,
  2253. + VMAPPLE_AES_2,
  2254. + VMAPPLE_BDOOR,
  2255. + VMAPPLE_MEMMAP_LAST,
  2256. +};
  2257. +
  2258. +static MemMapEntry memmap[] = {
  2259. + [VMAPPLE_FIRMWARE] = { 0x00100000, 0x00100000 },
  2260. + [VMAPPLE_CONFIG] = { 0x00400000, 0x00010000 },
  2261. +
  2262. + [VMAPPLE_GIC_DIST] = { 0x10000000, 0x00010000 },
  2263. + [VMAPPLE_GIC_REDIST] = { 0x10010000, 0x00400000 },
  2264. +
  2265. + [VMAPPLE_UART] = { 0x20010000, 0x00010000 },
  2266. + [VMAPPLE_RTC] = { 0x20050000, 0x00001000 },
  2267. + [VMAPPLE_GPIO] = { 0x20060000, 0x00001000 },
  2268. + [VMAPPLE_PVPANIC] = { 0x20070000, 0x00000002 },
  2269. + [VMAPPLE_BDOOR] = { 0x30000000, 0x00200000 },
  2270. + [VMAPPLE_APV_GFX] = { 0x30200000, 0x00010000 },
  2271. + [VMAPPLE_APV_IOSFC] = { 0x30210000, 0x00010000 },
  2272. + [VMAPPLE_AES_1] = { 0x30220000, 0x00004000 },
  2273. + [VMAPPLE_AES_2] = { 0x30230000, 0x00004000 },
  2274. + [VMAPPLE_PCIE_ECAM] = { 0x40000000, 0x10000000 },
  2275. + [VMAPPLE_PCIE_MMIO] = { 0x50000000, 0x1fff0000 },
  2276. +
  2277. + /* Actual RAM size depends on configuration */
  2278. + [VMAPPLE_MEM] = { 0x70000000ULL, GiB},
  2279. +};
  2280. +
  2281. +static const int irqmap[] = {
  2282. + [VMAPPLE_UART] = 1,
  2283. + [VMAPPLE_RTC] = 2,
  2284. + [VMAPPLE_GPIO] = 0x5,
  2285. + [VMAPPLE_APV_IOSFC] = 0x10,
  2286. + [VMAPPLE_APV_GFX] = 0x11,
  2287. + [VMAPPLE_AES_1] = 0x12,
  2288. + [VMAPPLE_PCIE] = 0x20,
  2289. +};
  2290. +
  2291. +#define GPEX_NUM_IRQS 16
  2292. +
  2293. +static void create_bdif(VMAppleMachineState *vms, MemoryRegion *mem)
  2294. +{
  2295. + DeviceState *bdif;
  2296. + SysBusDevice *bdif_sb;
  2297. + DriveInfo *di_aux = drive_get(IF_PFLASH, 0, 0);
  2298. + DriveInfo *di_root = drive_get(IF_PFLASH, 0, 1);
  2299. +
  2300. + if (!di_aux) {
  2301. + error_report("No AUX device found. Please specify one as pflash drive");
  2302. + exit(1);
  2303. + }
  2304. +
  2305. + if (!di_root) {
  2306. + /* Fall back to the first IF_VIRTIO device as root device */
  2307. + di_root = drive_get(IF_VIRTIO, 0, 0);
  2308. + }
  2309. +
  2310. + if (!di_root) {
  2311. + error_report("No root device found. Please specify one as virtio drive");
  2312. + exit(1);
  2313. + }
  2314. +
  2315. + /* PV backdoor device */
  2316. + bdif = qdev_new(TYPE_VMAPPLE_BDIF);
  2317. + bdif_sb = SYS_BUS_DEVICE(bdif);
  2318. + sysbus_mmio_map(bdif_sb, 0, vms->memmap[VMAPPLE_BDOOR].base);
  2319. +
  2320. + qdev_prop_set_drive(DEVICE(bdif), "aux", blk_by_legacy_dinfo(di_aux));
  2321. + qdev_prop_set_drive(DEVICE(bdif), "root", blk_by_legacy_dinfo(di_root));
  2322. +
  2323. + sysbus_realize_and_unref(bdif_sb, &error_fatal);
  2324. +}
  2325. +
  2326. +static void create_pvpanic(VMAppleMachineState *vms, MemoryRegion *mem)
  2327. +{
  2328. + SysBusDevice *cfg;
  2329. +
  2330. + vms->cfg = qdev_new(TYPE_PVPANIC_MMIO_DEVICE);
  2331. + cfg = SYS_BUS_DEVICE(vms->cfg);
  2332. + sysbus_mmio_map(cfg, 0, vms->memmap[VMAPPLE_PVPANIC].base);
  2333. +
  2334. + sysbus_realize_and_unref(cfg, &error_fatal);
  2335. +}
  2336. +
  2337. +static void create_cfg(VMAppleMachineState *vms, MemoryRegion *mem)
  2338. +{
  2339. + SysBusDevice *cfg;
  2340. + MachineState *machine = MACHINE(vms);
  2341. + uint32_t rnd = 1;
  2342. +
  2343. + vms->cfg = qdev_new(TYPE_VMAPPLE_CFG);
  2344. + cfg = SYS_BUS_DEVICE(vms->cfg);
  2345. + sysbus_mmio_map(cfg, 0, vms->memmap[VMAPPLE_CONFIG].base);
  2346. +
  2347. + qemu_guest_getrandom_nofail(&rnd, sizeof(rnd));
  2348. +
  2349. + qdev_prop_set_uint32(vms->cfg, "nr-cpus", machine->smp.cpus);
  2350. + qdev_prop_set_uint64(vms->cfg, "ecid", vms->uuid);
  2351. + qdev_prop_set_uint64(vms->cfg, "ram-size", machine->ram_size);
  2352. + qdev_prop_set_uint32(vms->cfg, "rnd", rnd);
  2353. +
  2354. + sysbus_realize_and_unref(cfg, &error_fatal);
  2355. +}
  2356. +
  2357. +static void create_gfx(VMAppleMachineState *vms, MemoryRegion *mem)
  2358. +{
  2359. + int irq_gfx = vms->irqmap[VMAPPLE_APV_GFX];
  2360. + int irq_iosfc = vms->irqmap[VMAPPLE_APV_IOSFC];
  2361. + SysBusDevice *aes;
  2362. +
  2363. + aes = SYS_BUS_DEVICE(qdev_new("apple-gfx"));
  2364. + sysbus_mmio_map(aes, 0, vms->memmap[VMAPPLE_APV_GFX].base);
  2365. + sysbus_mmio_map(aes, 1, vms->memmap[VMAPPLE_APV_IOSFC].base);
  2366. + sysbus_connect_irq(aes, 0, qdev_get_gpio_in(vms->gic, irq_gfx));
  2367. + sysbus_connect_irq(aes, 1, qdev_get_gpio_in(vms->gic, irq_iosfc));
  2368. + sysbus_realize_and_unref(aes, &error_fatal);
  2369. +}
  2370. +
  2371. +static void create_aes(VMAppleMachineState *vms, MemoryRegion *mem)
  2372. +{
  2373. + int irq = vms->irqmap[VMAPPLE_AES_1];
  2374. + SysBusDevice *aes;
  2375. +
  2376. + aes = SYS_BUS_DEVICE(qdev_new("apple-aes"));
  2377. + sysbus_mmio_map(aes, 0, vms->memmap[VMAPPLE_AES_1].base);
  2378. + sysbus_mmio_map(aes, 1, vms->memmap[VMAPPLE_AES_2].base);
  2379. + sysbus_connect_irq(aes, 0, qdev_get_gpio_in(vms->gic, irq));
  2380. + sysbus_realize_and_unref(aes, &error_fatal);
  2381. +}
  2382. +
  2383. +static inline int arm_gic_ppi_index(int cpu_nr, int ppi_index)
  2384. +{
  2385. + return NUM_IRQS + cpu_nr * GIC_INTERNAL + ppi_index;
  2386. +}
  2387. +
  2388. +static void create_gic(VMAppleMachineState *vms, MemoryRegion *mem)
  2389. +{
  2390. + MachineState *ms = MACHINE(vms);
  2391. + /* We create a standalone GIC */
  2392. + SysBusDevice *gicbusdev;
  2393. + int i;
  2394. + unsigned int smp_cpus = ms->smp.cpus;
  2395. +
  2396. + vms->gic = qdev_new(gicv3_class_name());
  2397. + qdev_prop_set_uint32(vms->gic, "revision", 3);
  2398. + qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus);
  2399. + /*
  2400. + * Note that the num-irq property counts both internal and external
  2401. + * interrupts; there are always 32 of the former (mandated by GIC spec).
  2402. + */
  2403. + qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32);
  2404. +
  2405. + uint32_t redist0_capacity =
  2406. + vms->memmap[VMAPPLE_GIC_REDIST].size / GICV3_REDIST_SIZE;
  2407. + uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
  2408. +
  2409. + qdev_prop_set_uint32(vms->gic, "len-redist-region-count", 1);
  2410. + qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count);
  2411. +
  2412. + gicbusdev = SYS_BUS_DEVICE(vms->gic);
  2413. + sysbus_realize_and_unref(gicbusdev, &error_fatal);
  2414. + sysbus_mmio_map(gicbusdev, 0, vms->memmap[VMAPPLE_GIC_DIST].base);
  2415. + sysbus_mmio_map(gicbusdev, 1, vms->memmap[VMAPPLE_GIC_REDIST].base);
  2416. +
  2417. + /*
  2418. + * Wire the outputs from each CPU's generic timer and the GICv3
  2419. + * maintenance interrupt signal to the appropriate GIC PPI inputs,
  2420. + * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
  2421. + */
  2422. + for (i = 0; i < smp_cpus; i++) {
  2423. + DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
  2424. +
  2425. + /* Map the virt timer to PPI 27 */
  2426. + qdev_connect_gpio_out(cpudev, GTIMER_VIRT,
  2427. + qdev_get_gpio_in(vms->gic,
  2428. + arm_gic_ppi_index(i, 27)));
  2429. +
  2430. + /* Map the GIC IRQ and FIQ lines to CPU */
  2431. + sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
  2432. + sysbus_connect_irq(gicbusdev, i + smp_cpus,
  2433. + qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
  2434. + }
  2435. +}
  2436. +
  2437. +static void create_uart(const VMAppleMachineState *vms, int uart,
  2438. + MemoryRegion *mem, Chardev *chr)
  2439. +{
  2440. + hwaddr base = vms->memmap[uart].base;
  2441. + int irq = vms->irqmap[uart];
  2442. + DeviceState *dev = qdev_new(TYPE_PL011);
  2443. + SysBusDevice *s = SYS_BUS_DEVICE(dev);
  2444. +
  2445. + qdev_prop_set_chr(dev, "chardev", chr);
  2446. + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  2447. + memory_region_add_subregion(mem, base,
  2448. + sysbus_mmio_get_region(s, 0));
  2449. + sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
  2450. +}
  2451. +
  2452. +static void create_rtc(const VMAppleMachineState *vms)
  2453. +{
  2454. + hwaddr base = vms->memmap[VMAPPLE_RTC].base;
  2455. + int irq = vms->irqmap[VMAPPLE_RTC];
  2456. +
  2457. + sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq));
  2458. +}
  2459. +
  2460. +static DeviceState *gpio_key_dev;
  2461. +static void vmapple_powerdown_req(Notifier *n, void *opaque)
  2462. +{
  2463. + /* use gpio Pin 3 for power button event */
  2464. + qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1);
  2465. +}
  2466. +
  2467. +static void create_gpio_devices(const VMAppleMachineState *vms, int gpio,
  2468. + MemoryRegion *mem)
  2469. +{
  2470. + DeviceState *pl061_dev;
  2471. + hwaddr base = vms->memmap[gpio].base;
  2472. + int irq = vms->irqmap[gpio];
  2473. + SysBusDevice *s;
  2474. +
  2475. + pl061_dev = qdev_new("pl061");
  2476. + /* Pull lines down to 0 if not driven by the PL061 */
  2477. + qdev_prop_set_uint32(pl061_dev, "pullups", 0);
  2478. + qdev_prop_set_uint32(pl061_dev, "pulldowns", 0xff);
  2479. + s = SYS_BUS_DEVICE(pl061_dev);
  2480. + sysbus_realize_and_unref(s, &error_fatal);
  2481. + memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
  2482. + sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq));
  2483. + gpio_key_dev = sysbus_create_simple("gpio-key", -1,
  2484. + qdev_get_gpio_in(pl061_dev, 3));
  2485. +}
  2486. +
  2487. +static void vmapple_firmware_init(VMAppleMachineState *vms,
  2488. + MemoryRegion *sysmem)
  2489. +{
  2490. + hwaddr size = vms->memmap[VMAPPLE_FIRMWARE].size;
  2491. + hwaddr base = vms->memmap[VMAPPLE_FIRMWARE].base;
  2492. + const char *bios_name;
  2493. + int image_size;
  2494. + char *fname;
  2495. +
  2496. + bios_name = MACHINE(vms)->firmware;
  2497. + if (!bios_name) {
  2498. + error_report("No firmware specified");
  2499. + exit(1);
  2500. + }
  2501. +
  2502. + fname = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
  2503. + if (!fname) {
  2504. + error_report("Could not find ROM image '%s'", bios_name);
  2505. + exit(1);
  2506. + }
  2507. +
  2508. + memory_region_init_ram(&vms->fw_mr, NULL, "firmware", size, NULL);
  2509. + image_size = load_image_mr(fname, &vms->fw_mr);
  2510. +
  2511. + g_free(fname);
  2512. + if (image_size < 0) {
  2513. + error_report("Could not load ROM image '%s'", bios_name);
  2514. + exit(1);
  2515. + }
  2516. +
  2517. + memory_region_add_subregion(get_system_memory(), base, &vms->fw_mr);
  2518. +}
  2519. +
  2520. +static void create_pcie(VMAppleMachineState *vms)
  2521. +{
  2522. + hwaddr base_mmio = vms->memmap[VMAPPLE_PCIE_MMIO].base;
  2523. + hwaddr size_mmio = vms->memmap[VMAPPLE_PCIE_MMIO].size;
  2524. + hwaddr base_ecam = vms->memmap[VMAPPLE_PCIE_ECAM].base;
  2525. + hwaddr size_ecam = vms->memmap[VMAPPLE_PCIE_ECAM].size;
  2526. + int irq = vms->irqmap[VMAPPLE_PCIE];
  2527. + MemoryRegion *mmio_alias;
  2528. + MemoryRegion *mmio_reg;
  2529. + MemoryRegion *ecam_alias;
  2530. + MemoryRegion *ecam_reg;
  2531. + DeviceState *dev;
  2532. + int i;
  2533. + PCIHostState *pci;
  2534. + DeviceState *virtio_tablet;
  2535. + DeviceState *virtio_keyboard;
  2536. +
  2537. + dev = qdev_new(TYPE_GPEX_HOST);
  2538. + qdev_prop_set_uint32(dev, "nr-irqs", GPEX_NUM_IRQS);
  2539. + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
  2540. +
  2541. + /* Map only the first size_ecam bytes of ECAM space */
  2542. + ecam_alias = g_new0(MemoryRegion, 1);
  2543. + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
  2544. + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
  2545. + ecam_reg, 0, size_ecam);
  2546. + memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias);
  2547. +
  2548. + /*
  2549. + * Map the MMIO window from [0x50000000-0x7fff0000] in PCI space into
  2550. + * system address space at [0x50000000-0x7fff0000].
  2551. + */
  2552. + mmio_alias = g_new0(MemoryRegion, 1);
  2553. + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
  2554. + memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
  2555. + mmio_reg, base_mmio, size_mmio);
  2556. + memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias);
  2557. +
  2558. + for (i = 0; i < GPEX_NUM_IRQS; i++) {
  2559. + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
  2560. + qdev_get_gpio_in(vms->gic, irq + i));
  2561. + gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
  2562. + }
  2563. +
  2564. + pci = PCI_HOST_BRIDGE(dev);
  2565. + vms->bus = pci->bus;
  2566. + if (vms->bus) {
  2567. + for (i = 0; i < nb_nics; i++) {
  2568. + NICInfo *nd = &nd_table[i];
  2569. +
  2570. + if (!nd->model) {
  2571. + nd->model = g_strdup("virtio");
  2572. + }
  2573. +
  2574. + pci_nic_init_nofail(nd, pci->bus, nd->model, NULL);
  2575. + }
  2576. + }
  2577. +
  2578. + virtio_tablet = qdev_new("virtio-tablet-pci");
  2579. + qdev_realize(virtio_tablet, BUS(pci->bus), &error_fatal);
  2580. + object_unref(virtio_tablet);
  2581. +
  2582. + virtio_keyboard = qdev_new("virtio-keyboard-pci");
  2583. + qdev_realize(virtio_keyboard, BUS(pci->bus), &error_fatal);
  2584. + object_unref(virtio_keyboard);
  2585. +}
  2586. +
  2587. +static void vmapple_reset(void *opaque)
  2588. +{
  2589. + VMAppleMachineState *vms = opaque;
  2590. + hwaddr base = vms->memmap[VMAPPLE_FIRMWARE].base;
  2591. +
  2592. + cpu_set_pc(first_cpu, base);
  2593. +}
  2594. +
  2595. +static void mach_vmapple_init(MachineState *machine)
  2596. +{
  2597. + VMAppleMachineState *vms = VMAPPLE_MACHINE(machine);
  2598. + MachineClass *mc = MACHINE_GET_CLASS(machine);
  2599. + const CPUArchIdList *possible_cpus;
  2600. + MemoryRegion *sysmem = get_system_memory();
  2601. + int n;
  2602. + unsigned int smp_cpus = machine->smp.cpus;
  2603. + unsigned int max_cpus = machine->smp.max_cpus;
  2604. +
  2605. + vms->memmap = memmap;
  2606. +
  2607. + possible_cpus = mc->possible_cpu_arch_ids(machine);
  2608. + assert(possible_cpus->len == max_cpus);
  2609. + for (n = 0; n < possible_cpus->len; n++) {
  2610. + Object *cpu;
  2611. + CPUState *cs;
  2612. +
  2613. + if (n >= smp_cpus) {
  2614. + break;
  2615. + }
  2616. +
  2617. + cpu = object_new(possible_cpus->cpus[n].type);
  2618. + object_property_set_int(cpu, "mp-affinity",
  2619. + possible_cpus->cpus[n].arch_id, NULL);
  2620. +
  2621. + cs = CPU(cpu);
  2622. + cs->cpu_index = n;
  2623. +
  2624. + numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpu),
  2625. + &error_fatal);
  2626. +
  2627. + object_property_set_bool(cpu, "has_el3", false, NULL);
  2628. + object_property_set_bool(cpu, "has_el2", false, NULL);
  2629. + object_property_set_int(cpu, "psci-conduit", QEMU_PSCI_CONDUIT_HVC,
  2630. + NULL);
  2631. +
  2632. + /* Secondary CPUs start in PSCI powered-down state */
  2633. + if (n > 0) {
  2634. + object_property_set_bool(cpu, "start-powered-off", true, NULL);
  2635. + }
  2636. +
  2637. + object_property_set_link(cpu, "memory", OBJECT(sysmem), &error_abort);
  2638. + qdev_realize(DEVICE(cpu), NULL, &error_fatal);
  2639. + object_unref(cpu);
  2640. + }
  2641. +
  2642. + memory_region_add_subregion(sysmem, vms->memmap[VMAPPLE_MEM].base,
  2643. + machine->ram);
  2644. +
  2645. + create_gic(vms, sysmem);
  2646. + create_bdif(vms, sysmem);
  2647. + create_pvpanic(vms, sysmem);
  2648. + create_aes(vms, sysmem);
  2649. + create_gfx(vms, sysmem);
  2650. + create_uart(vms, VMAPPLE_UART, sysmem, serial_hd(0));
  2651. + create_rtc(vms);
  2652. + create_pcie(vms);
  2653. +
  2654. + create_gpio_devices(vms, VMAPPLE_GPIO, sysmem);
  2655. +
  2656. + vmapple_firmware_init(vms, sysmem);
  2657. + create_cfg(vms, sysmem);
  2658. +
  2659. + /* connect powerdown request */
  2660. + vms->powerdown_notifier.notify = vmapple_powerdown_req;
  2661. + qemu_register_powerdown_notifier(&vms->powerdown_notifier);
  2662. +
  2663. + vms->bootinfo.ram_size = machine->ram_size;
  2664. + vms->bootinfo.board_id = -1;
  2665. + vms->bootinfo.loader_start = vms->memmap[VMAPPLE_MEM].base;
  2666. + vms->bootinfo.skip_dtb_autoload = true;
  2667. + vms->bootinfo.firmware_loaded = true;
  2668. + arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo);
  2669. +
  2670. + qemu_register_reset(vmapple_reset, vms);
  2671. +}
  2672. +
  2673. +static CpuInstanceProperties
  2674. +vmapple_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
  2675. +{
  2676. + MachineClass *mc = MACHINE_GET_CLASS(ms);
  2677. + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
  2678. +
  2679. + assert(cpu_index < possible_cpus->len);
  2680. + return possible_cpus->cpus[cpu_index].props;
  2681. +}
  2682. +
  2683. +
  2684. +static int64_t vmapple_get_default_cpu_node_id(const MachineState *ms, int idx)
  2685. +{
  2686. + return idx % ms->numa_state->num_nodes;
  2687. +}
  2688. +
  2689. +static const CPUArchIdList *vmapple_possible_cpu_arch_ids(MachineState *ms)
  2690. +{
  2691. + int n;
  2692. + unsigned int max_cpus = ms->smp.max_cpus;
  2693. +
  2694. + if (ms->possible_cpus) {
  2695. + assert(ms->possible_cpus->len == max_cpus);
  2696. + return ms->possible_cpus;
  2697. + }
  2698. +
  2699. + ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
  2700. + sizeof(CPUArchId) * max_cpus);
  2701. + ms->possible_cpus->len = max_cpus;
  2702. + for (n = 0; n < ms->possible_cpus->len; n++) {
  2703. + ms->possible_cpus->cpus[n].type = ms->cpu_type;
  2704. + ms->possible_cpus->cpus[n].arch_id =
  2705. + arm_cpu_mp_affinity(n, GICV3_TARGETLIST_BITS);
  2706. + ms->possible_cpus->cpus[n].props.has_thread_id = true;
  2707. + ms->possible_cpus->cpus[n].props.thread_id = n;
  2708. + }
  2709. + return ms->possible_cpus;
  2710. +}
  2711. +
  2712. +static void vmapple_get_uuid(Object *obj, Visitor *v, const char *name,
  2713. + void *opaque, Error **errp)
  2714. +{
  2715. + VMAppleMachineState *vms = VMAPPLE_MACHINE(obj);
  2716. + uint64_t value = be64_to_cpu(vms->uuid);
  2717. +
  2718. + visit_type_uint64(v, name, &value, errp);
  2719. +}
  2720. +
  2721. +static void vmapple_set_uuid(Object *obj, Visitor *v, const char *name,
  2722. + void *opaque, Error **errp)
  2723. +{
  2724. + VMAppleMachineState *vms = VMAPPLE_MACHINE(obj);
  2725. + Error *error = NULL;
  2726. + uint64_t value;
  2727. +
  2728. + visit_type_uint64(v, name, &value, &error);
  2729. + if (error) {
  2730. + error_propagate(errp, error);
  2731. + return;
  2732. + }
  2733. +
  2734. + vms->uuid = cpu_to_be64(value);
  2735. +}
  2736. +
  2737. +static void vmapple_machine_class_init(ObjectClass *oc, void *data)
  2738. +{
  2739. + MachineClass *mc = MACHINE_CLASS(oc);
  2740. +
  2741. + mc->init = mach_vmapple_init;
  2742. + mc->max_cpus = 32;
  2743. + mc->block_default_type = IF_VIRTIO;
  2744. + mc->no_cdrom = 1;
  2745. + mc->pci_allow_0_address = true;
  2746. + mc->minimum_page_bits = 12;
  2747. + mc->possible_cpu_arch_ids = vmapple_possible_cpu_arch_ids;
  2748. + mc->cpu_index_to_instance_props = vmapple_cpu_index_to_props;
  2749. + if (hvf_enabled()) {
  2750. + mc->default_cpu_type = ARM_CPU_TYPE_NAME("host");
  2751. + } else {
  2752. + mc->default_cpu_type = ARM_CPU_TYPE_NAME("max");
  2753. + }
  2754. + mc->get_default_cpu_node_id = vmapple_get_default_cpu_node_id;
  2755. + mc->default_ram_id = "mach-vmapple.ram";
  2756. +
  2757. + object_register_sugar_prop(TYPE_VIRTIO_PCI, "disable-legacy",
  2758. + "on", true);
  2759. +
  2760. + object_class_property_add(oc, "uuid", "uint64", vmapple_get_uuid,
  2761. + vmapple_set_uuid, NULL, NULL);
  2762. + object_class_property_set_description(oc, "uuid", "Machine UUID (SDOM)");
  2763. +}
  2764. +
  2765. +static void vmapple_instance_init(Object *obj)
  2766. +{
  2767. + VMAppleMachineState *vms = VMAPPLE_MACHINE(obj);
  2768. +
  2769. + vms->irqmap = irqmap;
  2770. +}
  2771. +
  2772. +static const TypeInfo vmapple_machine_info = {
  2773. + .name = TYPE_VMAPPLE_MACHINE,
  2774. + .parent = TYPE_MACHINE,
  2775. + .abstract = true,
  2776. + .instance_size = sizeof(VMAppleMachineState),
  2777. + .class_size = sizeof(VMAppleMachineClass),
  2778. + .class_init = vmapple_machine_class_init,
  2779. + .instance_init = vmapple_instance_init,
  2780. +};
  2781. +
  2782. +static void machvmapple_machine_init(void)
  2783. +{
  2784. + type_register_static(&vmapple_machine_info);
  2785. +}
  2786. +type_init(machvmapple_machine_init);
  2787. +
  2788. +static void vmapple_machine_8_1_options(MachineClass *mc)
  2789. +{
  2790. +}
  2791. +DEFINE_VMAPPLE_MACHINE_AS_LATEST(8, 1)
  2792. +
  2793. diff --git a/hw/xtensa/virt.c b/hw/xtensa/virt.c
  2794. index a6cf646e99..c23c540e87 100644
  2795. --- a/hw/xtensa/virt.c
  2796. +++ b/hw/xtensa/virt.c
  2797. @@ -93,7 +93,7 @@ static void create_pcie(MachineState *ms, CPUXtensaState *env, int irq_base,
  2798. /* Connect IRQ lines. */
  2799. extints = xtensa_get_extints(env);
  2800.  
  2801. - for (i = 0; i < GPEX_NUM_IRQS; i++) {
  2802. + for (i = 0; i < PCI_NUM_PINS; i++) {
  2803. void *q = extints[irq_base + i];
  2804.  
  2805. sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, q);
  2806. diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
  2807. index fab94165d0..f9e7c1ea17 100644
  2808. --- a/include/hw/misc/pvpanic.h
  2809. +++ b/include/hw/misc/pvpanic.h
  2810. @@ -20,6 +20,7 @@
  2811.  
  2812. #define TYPE_PVPANIC_ISA_DEVICE "pvpanic"
  2813. #define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci"
  2814. +#define TYPE_PVPANIC_MMIO_DEVICE "pvpanic-mmio"
  2815.  
  2816. #define PVPANIC_IOPORT_PROP "ioport"
  2817.  
  2818. diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h
  2819. index b0240bd768..098dc4d1cc 100644
  2820. --- a/include/hw/pci-host/gpex.h
  2821. +++ b/include/hw/pci-host/gpex.h
  2822. @@ -32,8 +32,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(GPEXHost, GPEX_HOST)
  2823. #define TYPE_GPEX_ROOT_DEVICE "gpex-root"
  2824. OBJECT_DECLARE_SIMPLE_TYPE(GPEXRootState, GPEX_ROOT_DEVICE)
  2825.  
  2826. -#define GPEX_NUM_IRQS 4
  2827. -
  2828. struct GPEXRootState {
  2829. /*< private >*/
  2830. PCIDevice parent_obj;
  2831. @@ -51,8 +49,9 @@ struct GPEXHost {
  2832. MemoryRegion io_mmio;
  2833. MemoryRegion io_ioport_window;
  2834. MemoryRegion io_mmio_window;
  2835. - qemu_irq irq[GPEX_NUM_IRQS];
  2836. - int irq_num[GPEX_NUM_IRQS];
  2837. + uint32_t nr_irqs;
  2838. + qemu_irq *irq;
  2839. + int *irq_num;
  2840.  
  2841. bool allow_unmapped_accesses;
  2842. };
  2843. diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
  2844. index e4386ebb20..74e589a298 100644
  2845. --- a/include/hw/pci/pci_ids.h
  2846. +++ b/include/hw/pci/pci_ids.h
  2847. @@ -188,6 +188,7 @@
  2848. #define PCI_DEVICE_ID_APPLE_UNI_N_AGP 0x0020
  2849. #define PCI_DEVICE_ID_APPLE_U3_AGP 0x004b
  2850. #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC 0x0021
  2851. +#define PCI_DEVICE_ID_APPLE_VIRTIO_BLK 0x1a00
  2852.  
  2853. #define PCI_VENDOR_ID_SUN 0x108e
  2854. #define PCI_DEVICE_ID_SUN_EBUS 0x1000
  2855. diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
  2856. index dafec432ce..7117ce754c 100644
  2857. --- a/include/hw/virtio/virtio-blk.h
  2858. +++ b/include/hw/virtio/virtio-blk.h
  2859. @@ -46,6 +46,7 @@ struct VirtIOBlkConf
  2860. uint32_t max_discard_sectors;
  2861. uint32_t max_write_zeroes_sectors;
  2862. bool x_enable_wce_if_config_wce;
  2863. + uint32_t x_apple_type;
  2864. };
  2865.  
  2866. struct VirtIOBlockDataPlane;
  2867. diff --git a/include/hw/vmapple/bdif.h b/include/hw/vmapple/bdif.h
  2868. new file mode 100644
  2869. index 0000000000..65ee43457b
  2870. --- /dev/null
  2871. +++ b/include/hw/vmapple/bdif.h
  2872. @@ -0,0 +1,31 @@
  2873. +/*
  2874. + * VMApple Backdoor Interface
  2875. + *
  2876. + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  2877. + *
  2878. + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  2879. + * See the COPYING file in the top-level directory.
  2880. + */
  2881. +
  2882. +#ifndef HW_VMAPPLE_BDIF_H
  2883. +#define HW_VMAPPLE_BDIF_H
  2884. +
  2885. +#include "hw/sysbus.h"
  2886. +#include "qom/object.h"
  2887. +
  2888. +#define TYPE_VMAPPLE_BDIF "vmapple-bdif"
  2889. +OBJECT_DECLARE_SIMPLE_TYPE(VMAppleBdifState, VMAPPLE_BDIF)
  2890. +
  2891. +struct VMAppleBdifState {
  2892. + /* <private> */
  2893. + SysBusDevice parent_obj;
  2894. +
  2895. + /* <public> */
  2896. + BlockBackend *aux;
  2897. + BlockBackend *root;
  2898. + MemoryRegion mmio;
  2899. +};
  2900. +
  2901. +#define VMAPPLE_BDIF_SIZE 0x00200000
  2902. +
  2903. +#endif /* HW_VMAPPLE_BDIF_H */
  2904. diff --git a/include/hw/vmapple/cfg.h b/include/hw/vmapple/cfg.h
  2905. new file mode 100644
  2906. index 0000000000..3337064e44
  2907. --- /dev/null
  2908. +++ b/include/hw/vmapple/cfg.h
  2909. @@ -0,0 +1,68 @@
  2910. +/*
  2911. + * VMApple Configuration Region
  2912. + *
  2913. + * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  2914. + *
  2915. + * This work is licensed under the terms of the GNU GPL, version 2 or later.
  2916. + * See the COPYING file in the top-level directory.
  2917. + */
  2918. +
  2919. +#ifndef HW_VMAPPLE_CFG_H
  2920. +#define HW_VMAPPLE_CFG_H
  2921. +
  2922. +#include "hw/sysbus.h"
  2923. +#include "qom/object.h"
  2924. +#include "net/net.h"
  2925. +
  2926. +typedef struct VMAppleCfg {
  2927. + uint32_t version; /* 0x000 */
  2928. + uint32_t nr_cpus; /* 0x004 */
  2929. + uint32_t unk1; /* 0x008 */
  2930. + uint32_t unk2; /* 0x00c */
  2931. + uint32_t unk3; /* 0x010 */
  2932. + uint32_t unk4; /* 0x014 */
  2933. + uint64_t ecid; /* 0x018 */
  2934. + uint64_t ram_size; /* 0x020 */
  2935. + uint32_t run_installer1; /* 0x028 */
  2936. + uint32_t unk5; /* 0x02c */
  2937. + uint32_t unk6; /* 0x030 */
  2938. + uint32_t run_installer2; /* 0x034 */
  2939. + uint32_t rnd; /* 0x038 */
  2940. + uint32_t unk7; /* 0x03c */
  2941. + MACAddr mac_en0; /* 0x040 */
  2942. + uint8_t pad1[2];
  2943. + MACAddr mac_en1; /* 0x048 */
  2944. + uint8_t pad2[2];
  2945. + MACAddr mac_wifi0; /* 0x050 */
  2946. + uint8_t pad3[2];
  2947. + MACAddr mac_bt0; /* 0x058 */
  2948. + uint8_t pad4[2];
  2949. + uint8_t reserved[0xa0]; /* 0x060 */
  2950. + uint32_t cpu_ids[0x80]; /* 0x100 */
  2951. + uint8_t scratch[0x200]; /* 0x180 */
  2952. + char serial[32]; /* 0x380 */
  2953. + char unk8[32]; /* 0x3a0 */
  2954. + char model[32]; /* 0x3c0 */
  2955. + uint8_t unk9[32]; /* 0x3e0 */
  2956. + uint32_t unk10; /* 0x400 */
  2957. + char soc_name[32]; /* 0x404 */
  2958. +} VMAppleCfg;
  2959. +
  2960. +#define TYPE_VMAPPLE_CFG "vmapple-cfg"
  2961. +OBJECT_DECLARE_SIMPLE_TYPE(VMAppleCfgState, VMAPPLE_CFG)
  2962. +
  2963. +struct VMAppleCfgState {
  2964. + /* <private> */
  2965. + SysBusDevice parent_obj;
  2966. + VMAppleCfg cfg;
  2967. +
  2968. + /* <public> */
  2969. + MemoryRegion mem;
  2970. + char *serial;
  2971. + char *model;
  2972. + char *soc_name;
  2973. +};
  2974. +
  2975. +#define VMAPPLE_CFG_SIZE 0x00010000
  2976. +
  2977. +#endif /* HW_VMAPPLE_CFG_H */
  2978. diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard-headers/linux/virtio_blk.h
  2979. index d7be3cf5e4..1630262121 100644
  2980. --- a/include/standard-headers/linux/virtio_blk.h
  2981. +++ b/include/standard-headers/linux/virtio_blk.h
  2982. @@ -204,6 +204,9 @@ struct virtio_blk_config {
  2983. /* Reset All zones command */
  2984. #define VIRTIO_BLK_T_ZONE_RESET_ALL 26
  2985.  
  2986. +/* Write zeroes command */
  2987. +#define VIRTIO_BLK_T_APPLE1 0x10000
  2988. +
  2989. #ifndef VIRTIO_BLK_NO_LEGACY
  2990. /* Barrier before this op. */
  2991. #define VIRTIO_BLK_T_BARRIER 0x80000000
  2992. diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
  2993. index 718beddcdd..ee8103bee4 100644
  2994. --- a/include/sysemu/hvf_int.h
  2995. +++ b/include/sysemu/hvf_int.h
  2996. @@ -40,7 +40,7 @@ typedef struct hvf_vcpu_caps {
  2997.  
  2998. struct HVFState {
  2999. AccelState parent;
  3000. - hvf_slot slots[32];
  3001. + hvf_slot slots[512];
  3002. int num_slots;
  3003.  
  3004. hvf_vcpu_caps *hvf_caps;
  3005. diff --git a/meson.build b/meson.build
  3006. index 98e68ef0b1..d34310b5eb 100644
  3007. --- a/meson.build
  3008. +++ b/meson.build
  3009. @@ -224,7 +224,9 @@ qemu_ldflags = []
  3010. if targetos == 'darwin'
  3011. # Disable attempts to use ObjectiveC features in os/object.h since they
  3012. # won't work when we're compiling with gcc as a C compiler.
  3013. - qemu_common_flags += '-DOS_OBJECT_USE_OBJC=0'
  3014. + if compiler.get_id() == 'gcc'
  3015. + qemu_common_flags += '-DOS_OBJECT_USE_OBJC=0'
  3016. + endif
  3017. elif targetos == 'solaris'
  3018. # needed for CMSG_ macros in sys/socket.h
  3019. qemu_common_flags += '-D_XOPEN_SOURCE=600'
  3020. @@ -605,6 +607,8 @@ socket = []
  3021. version_res = []
  3022. coref = []
  3023. iokit = []
  3024. +pvg = []
  3025. +metal = []
  3026. emulator_link_args = []
  3027. nvmm =not_found
  3028. hvf = not_found
  3029. @@ -628,6 +632,8 @@ elif targetos == 'darwin'
  3030. coref = dependency('appleframeworks', modules: 'CoreFoundation')
  3031. iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
  3032. host_dsosuf = '.dylib'
  3033. + pvg = dependency('appleframeworks', modules: 'ParavirtualizedGraphics')
  3034. + metal = dependency('appleframeworks', modules: 'Metal')
  3035. elif targetos == 'sunos'
  3036. socket = [cc.find_library('socket'),
  3037. cc.find_library('nsl'),
  3038. @@ -3280,6 +3286,7 @@ if have_system
  3039. 'hw/usb',
  3040. 'hw/vfio',
  3041. 'hw/virtio',
  3042. + 'hw/vmapple',
  3043. 'hw/watchdog',
  3044. 'hw/xen',
  3045. 'hw/gpio',
  3046. diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
  3047. index 8fce64bbf6..13dec00f37 100644
  3048. --- a/target/arm/hvf/hvf.c
  3049. +++ b/target/arm/hvf/hvf.c
  3050. @@ -179,6 +179,7 @@ void hvf_arm_init_debug(void)
  3051. #define SYSREG_OSLSR_EL1 SYSREG(2, 0, 1, 1, 4)
  3052. #define SYSREG_OSDLR_EL1 SYSREG(2, 0, 1, 3, 4)
  3053. #define SYSREG_CNTPCT_EL0 SYSREG(3, 3, 14, 0, 1)
  3054. +#define SYSREG_CNTP_CTL_EL0 SYSREG(3, 3, 14, 2, 1)
  3055. #define SYSREG_PMCR_EL0 SYSREG(3, 3, 9, 12, 0)
  3056. #define SYSREG_PMUSERENR_EL0 SYSREG(3, 3, 9, 14, 0)
  3057. #define SYSREG_PMCNTENSET_EL0 SYSREG(3, 3, 9, 12, 1)
  3058. @@ -1551,6 +1552,12 @@ static int hvf_sysreg_write(CPUState *cpu, uint32_t reg, uint64_t val)
  3059. case SYSREG_OSLAR_EL1:
  3060. env->cp15.oslsr_el1 = val & 1;
  3061. break;
  3062. + case SYSREG_CNTP_CTL_EL0:
  3063. + /*
  3064. + * Guests should not rely on the physical counter, but macOS emits
  3065. + * disable writes to it. Let it do so, but ignore the requests.
  3066. + */
  3067. + break;
  3068. case SYSREG_OSDLR_EL1:
  3069. /* Dummy register */
  3070. break;
Add Comment
Please, Sign In to add comment