Re: [PATCH v8 04/15] hw/display/apple-gfx: Adds configurable mode list

2024-11-09 Thread Akihiko Odaki

On 2024/11/08 23:46, Phil Dennis-Jordan wrote:

This change adds a property 'display_modes' on the graphics device
which permits specifying a list of display modes. (screen resolution
and refresh rate)

The property is an array of a custom type to make the syntax slightly
less awkward to use, for example:

-device '{"driver":"apple-gfx-pci", "display-modes":["1920x1080@60", 
"3840x2160@60"]}'

Signed-off-by: Phil Dennis-Jordan 
---

v4:

  * Switched to the native array property type, which recently gained
 command line support.
  * The property has also been added to the -mmio variant.
  * Tidied up the code a little.

v5:

  * Better error handling and buffer management in property parsing and
output.

v6:

  * Switched to using NSMutableArray for the mode list to avoid need for
allocating a temporary array - previously done with alloca.

v7:

  * Simplified error handling in property parsing

v8:

  * More consistent integer variable types.

  hw/display/apple-gfx-mmio.m |   8 +++
  hw/display/apple-gfx-pci.m  |   9 ++-
  hw/display/apple-gfx.h  |  12 
  hw/display/apple-gfx.m  | 136 +++-
  hw/display/trace-events |   2 +
  5 files changed, 147 insertions(+), 20 deletions(-)

diff --git a/hw/display/apple-gfx-mmio.m b/hw/display/apple-gfx-mmio.m
index 2c5f426886c..2e4d775a04b 100644
--- a/hw/display/apple-gfx-mmio.m
+++ b/hw/display/apple-gfx-mmio.m
@@ -259,6 +259,12 @@ static void apple_gfx_mmio_reset(Object *obj, ResetType 
type)
  [s->common.pgdev reset];
  }
  
+static Property apple_gfx_mmio_properties[] = {

+DEFINE_PROP_ARRAY("display-modes", AppleGFXMMIOState,
+  common.num_display_modes, common.display_modes,
+  qdev_prop_display_mode, AppleGFXDisplayMode),
+DEFINE_PROP_END_OF_LIST(),
+};
  
  static void apple_gfx_mmio_class_init(ObjectClass *klass, void *data)

  {
@@ -268,6 +274,8 @@ static void apple_gfx_mmio_class_init(ObjectClass *klass, 
void *data)
  rc->phases.hold = apple_gfx_mmio_reset;
  dc->hotpluggable = false;
  dc->realize = apple_gfx_mmio_realize;
+
+device_class_set_props(dc, apple_gfx_mmio_properties);
  }
  
  static TypeInfo apple_gfx_mmio_types[] = {

diff --git a/hw/display/apple-gfx-pci.m b/hw/display/apple-gfx-pci.m
index 8bd7c0df443..712a08a5c8f 100644
--- a/hw/display/apple-gfx-pci.m
+++ b/hw/display/apple-gfx-pci.m
@@ -112,6 +112,13 @@ static void apple_gfx_pci_reset(Object *obj, ResetType 
type)
  [s->common.pgdev reset];
  }
  
+static Property apple_gfx_pci_properties[] = {

+DEFINE_PROP_ARRAY("display-modes", AppleGFXPCIState,
+  common.num_display_modes, common.display_modes,
+  qdev_prop_display_mode, AppleGFXDisplayMode),
+DEFINE_PROP_END_OF_LIST(),
+};
+
  static void apple_gfx_pci_class_init(ObjectClass *klass, void *data)
  {
  DeviceClass *dc = DEVICE_CLASS(klass);
@@ -128,7 +135,7 @@ static void apple_gfx_pci_class_init(ObjectClass *klass, 
void *data)
  pci->class_id = PCI_CLASS_DISPLAY_OTHER;
  pci->realize = apple_gfx_pci_realize;
  
-// TODO: Property for setting mode list

+device_class_set_props(dc, apple_gfx_pci_properties);
  }
  
  static TypeInfo apple_gfx_pci_types[] = {

diff --git a/hw/display/apple-gfx.h b/hw/display/apple-gfx.h
index 14ac2af8fc3..a38bc1240a8 100644
--- a/hw/display/apple-gfx.h
+++ b/hw/display/apple-gfx.h
@@ -16,6 +16,7 @@
  #import 
  #include "qemu/typedefs.h"
  #include "exec/memory.h"
+#include "hw/qdev-properties.h"
  #include "ui/surface.h"
  
  @class PGDeviceDescriptor;

@@ -27,6 +28,7 @@
  
  typedef QTAILQ_HEAD(, PGTask_s) PGTaskList;
  
+struct AppleGFXDisplayMode;


typedef AppleGFXDisplayMode here so that we can use it in AppleGFXState.


  typedef struct AppleGFXState {
  /* Initialised on init/realize() */
  MemoryRegion iomem_gfx;
@@ -36,6 +38,8 @@ typedef struct AppleGFXState {
  id mtl;
  id mtl_queue;
  dispatch_queue_t render_queue;
+struct AppleGFXDisplayMode *display_modes;
+uint32_t num_display_modes;
  
  /* List `tasks` is protected by task_mutex */

  QemuMutex task_mutex;
@@ -54,6 +58,12 @@ typedef struct AppleGFXState {
  bool cursor_show;
  } AppleGFXState;
  
+typedef struct AppleGFXDisplayMode {

+uint16_t width_px;
+uint16_t height_px;
+uint16_t refresh_rate_hz;
+} AppleGFXDisplayMode;
+
  void apple_gfx_common_init(Object *obj, AppleGFXState *s, const char* 
obj_name);
  void apple_gfx_common_realize(AppleGFXState *s, PGDeviceDescriptor *desc,
Error **errp);
@@ -61,5 +71,7 @@ void* apple_gfx_host_ptr_for_gpa_range(uint64_t 
guest_physical,
 uint64_t length, bool read_only,
 MemoryRegion **mapping_in_region);
  
+extern const PropertyInfo qdev_prop_display_mode;

+
  #endif
  
diff --git a/hw/display/apple-gfx.m b/hw/display/apple

Re: [PATCH v8 03/15] hw/display/apple-gfx: Adds PCI implementation

2024-11-09 Thread Akihiko Odaki

On 2024/11/08 23:46, Phil Dennis-Jordan wrote:

This change wires up the PCI variant of the paravirtualised
graphics device, mainly useful for x86-64 macOS guests, implemented
by macOS's ParavirtualizedGraphics.framework. It builds on code
shared with the vmapple/mmio variant of the PVG device.

Signed-off-by: Phil Dennis-Jordan 
---

v4:

  * Threading improvements analogous to those in common apple-gfx code
and mmio device variant.
  * Smaller code review issues addressed.

v5:

  * Minor error handling improvement.

v6:

  * Removed an unused function parameter.

  hw/display/Kconfig |   4 +
  hw/display/apple-gfx-pci.m | 148 +
  hw/display/meson.build |   1 +
  3 files changed, 153 insertions(+)
  create mode 100644 hw/display/apple-gfx-pci.m

diff --git a/hw/display/Kconfig b/hw/display/Kconfig
index 6a9b7b19ada..2b53dfd7d26 100644
--- a/hw/display/Kconfig
+++ b/hw/display/Kconfig
@@ -149,3 +149,7 @@ config MAC_PVG_MMIO
  bool
  depends on MAC_PVG && AARCH64
  
+config MAC_PVG_PCI

+bool
+depends on MAC_PVG && PCI
+default y if PCI_DEVICES
diff --git a/hw/display/apple-gfx-pci.m b/hw/display/apple-gfx-pci.m
new file mode 100644
index 000..8bd7c0df443
--- /dev/null
+++ b/hw/display/apple-gfx-pci.m
@@ -0,0 +1,148 @@
+/*
+ * QEMU Apple ParavirtualizedGraphics.framework device, PCI variant
+ *
+ * Copyright © 2023-2024 Phil Dennis-Jordan
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * ParavirtualizedGraphics.framework is a set of libraries that macOS provides
+ * which implements 3d graphics passthrough to the host as well as a
+ * proprietary guest communication channel to drive it. This device model
+ * implements support to drive that library from within QEMU as a PCI device
+ * aimed primarily at x86-64 macOS VMs.
+ */
+
+#include "apple-gfx.h"
+#include "hw/pci/pci_device.h"
+#include "hw/pci/msi.h"
+#include "qapi/error.h"
+#include "trace.h"
+#import 
+
+OBJECT_DECLARE_SIMPLE_TYPE(AppleGFXPCIState, APPLE_GFX_PCI)
+
+struct AppleGFXPCIState {
+PCIDevice parent_obj;
+
+AppleGFXState common;
+};
+
+static const char* apple_gfx_pci_option_rom_path = NULL;
+
+static void apple_gfx_init_option_rom_path(void)
+{
+NSURL *option_rom_url = PGCopyOptionROMURL();
+const char *option_rom_path = option_rom_url.fileSystemRepresentation;
+apple_gfx_pci_option_rom_path = g_strdup(option_rom_path);
+[option_rom_url release];
+}
+
+static void apple_gfx_pci_init(Object *obj)
+{
+AppleGFXPCIState *s = APPLE_GFX_PCI(obj);
+
+if (!apple_gfx_pci_option_rom_path) {
+/* The following is done on device not class init to avoid running
+ * ObjC code before fork() in -daemonize mode. */
+PCIDeviceClass *pci = PCI_DEVICE_CLASS(object_get_class(obj));
+apple_gfx_init_option_rom_path();
+pci->romfile = apple_gfx_pci_option_rom_path;
+}
+
+apple_gfx_common_init(obj, &s->common, TYPE_APPLE_GFX_PCI);
+}
+
+typedef struct AppleGFXPCIInterruptJob {
+PCIDevice *device;
+uint32_t vector;
+} AppleGFXPCIInterruptJob;
+
+static void apple_gfx_pci_raise_interrupt(void *opaque)
+{
+AppleGFXPCIInterruptJob *job = opaque;
+
+if (msi_enabled(job->device)) {
+msi_notify(job->device, job->vector);
+}
+g_free(job);
+}
+
+static void apple_gfx_pci_interrupt(PCIDevice *dev, uint32_t vector)
+{
+AppleGFXPCIInterruptJob *job;
+
+trace_apple_gfx_raise_irq(vector);
+job = g_malloc0(sizeof(*job));
+job->device = dev;
+job->vector = vector;
+aio_bh_schedule_oneshot(qemu_get_aio_context(),
+apple_gfx_pci_raise_interrupt, job);
+}
+
+static void apple_gfx_pci_realize(PCIDevice *dev, Error **errp)
+{
+AppleGFXPCIState *s = APPLE_GFX_PCI(dev);
+int ret;
+
+pci_register_bar(dev, PG_PCI_BAR_MMIO,
+ PCI_BASE_ADDRESS_SPACE_MEMORY, &s->common.iomem_gfx);
+
+ret = msi_init(dev, 0x0 /* config offset; 0 = find space */,
+   PG_PCI_MAX_MSI_VECTORS, true /* msi64bit */,
+   false /*msi_per_vector_mask*/, errp);


Let's add whitespaces around msi_per_vector_mask for consistency:
/* msi_per_vector_mask */


+if (ret != 0) {
+return;
+}
+
+@autoreleasepool {
+PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
+desc.raiseInterrupt = ^(uint32_t vector) {
+apple_gfx_pci_interrupt(dev, vector);
+};
+
+apple_gfx_common_realize(&s->common, desc, errp);
+[desc release];
+desc = nil;
+}
+}
+
+static void apple_gfx_pci_reset(Object *obj, ResetType type)
+{
+AppleGFXPCIState *s = APPLE_GFX_PCI(obj);
+[s->common.pgdev reset];
+}
+
+static void apple_gfx_pci_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+PCIDeviceClass *pci = PCI_DEVICE_CLASS(klass);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+rc->phases.hold = a

Re: [PATCH v8 01/15] ui & main loop: Redesign of system-specific main thread event handling

2024-11-09 Thread Akihiko Odaki

On 2024/11/08 23:46, Phil Dennis-Jordan wrote:

macOS's Cocoa event handling must be done on the initial (main) thread
of the process. Furthermore, if library or application code uses
libdispatch, the main dispatch queue must be handling events on the main
thread as well.

So far, this has affected Qemu in both the Cocoa and SDL UIs, although
in different ways: the Cocoa UI replaces the default qemu_main function
with one that spins Qemu's internal main event loop off onto a
background thread. SDL (which uses Cocoa internally) on the other hand
uses a polling approach within Qemu's main event loop. Events are
polled during the SDL UI's dpy_refresh callback, which happens to run
on the main thread by default.


GTK should also do the same as SDL and requires treatment; I forgot to 
note that in previous reviews.




As UIs are mutually exclusive, this works OK as long as nothing else
needs platform-native event handling. In the next patch, a new device is
introduced based on the ParavirtualizedGraphics.framework in macOS.
This uses libdispatch internally, and only works when events are being
handled on the main runloop. With the current system, it works when
using either the Cocoa or the SDL UI. However, it does not when running
headless. Moreover, any attempt to install a similar scheme to the
Cocoa UI's main thread replacement fails when combined with the SDL
UI.

This change tidies up main thread management to be more flexible.

  * The qemu_main global function pointer is a custom function for the
main thread, and it may now be NULL. When it is, the main thread
runs the main Qemu loop. This represents the traditional setup.
  * When non-null, spawning the main Qemu event loop on a separate
thread is now done centrally rather than inside the Cocoa UI code.
  * For most platforms, qemu_main is indeed NULL by default, but on
Darwin, it defaults to a function that runs the CFRunLoop.
  * The Cocoa UI sets qemu_main to a function which runs the
NSApplication event handling runloop, as is usual for a Cocoa app.
  * The SDL UI overrides the qemu_main function to NULL, thus
specifying that Qemu's main loop must run on the main
thread.
  * For other UIs, or in the absence of UIs, the platform's default
behaviour is followed.

This means that on macOS, the platform's runloop events are always
handled, regardless of chosen UI. The new PV graphics device will
thus work in all configurations. There is no functional change on other
operating systems.

Signed-off-by: Phil Dennis-Jordan 
Reviewed-by: Akihiko Odaki 
---

v5:

  * Simplified the way of setting/clearing the main loop by going back
to setting qemu_main directly, but narrowing the scope of what it
needs to do, and it can now be NULL.

v6:

  * Folded function qemu_run_default_main_on_new_thread's code into
main()
  * Removed whitespace changes left over on lines near code removed
between v4 and v5

  include/qemu-main.h |  3 +--
  include/qemu/typedefs.h |  1 +
  system/main.c   | 50 ++
  ui/cocoa.m  | 54 ++---
  ui/sdl2.c   |  4 +++
  5 files changed, 64 insertions(+), 48 deletions(-)

diff --git a/include/qemu-main.h b/include/qemu-main.h
index 940960a7dbc..4bd0d667edc 100644
--- a/include/qemu-main.h
+++ b/include/qemu-main.h
@@ -5,7 +5,6 @@
  #ifndef QEMU_MAIN_H
  #define QEMU_MAIN_H
  
-int qemu_default_main(void);

-extern int (*qemu_main)(void);
+extern qemu_main_fn qemu_main;
  
  #endif /* QEMU_MAIN_H */

diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 3d84efcac47..b02cfe1f328 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -131,5 +131,6 @@ typedef struct IRQState *qemu_irq;
   * Function types
   */
  typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
+typedef int (*qemu_main_fn)(void);
  
  #endif /* QEMU_TYPEDEFS_H */

diff --git a/system/main.c b/system/main.c
index 9b91d21ea8c..d9397a6d5d0 100644
--- a/system/main.c
+++ b/system/main.c
@@ -24,13 +24,14 @@
  
  #include "qemu/osdep.h"

  #include "qemu-main.h"
+#include "qemu/main-loop.h"
  #include "sysemu/sysemu.h"
  
-#ifdef CONFIG_SDL

-#include 
+#ifdef CONFIG_DARWIN
+#include 
  #endif
  
-int qemu_default_main(void)

+static int qemu_default_main(void)
  {
  int status;
  
@@ -40,10 +41,49 @@ int qemu_default_main(void)

  return status;
  }
  
-int (*qemu_main)(void) = qemu_default_main;

+/*
+ * Various macOS system libraries, including the Cocoa UI and anything using
+ * libdispatch, such as ParavirtualizedGraphics.framework, requires that the
+ * main runloop, on the main (initial) thread be running or at least regularly
+ * polled for events. A special mode is therefore supported, where the QEMU
+ * main loop runs on a separate thread and the main thread handles the
+ * CF/Cocoa runloop.
+ */
+
+static void *call_qemu_default_main(void *opaque)
+{
+int status;

Re: [PATCH v8 11/15] hw/vmapple/bdif: Introduce vmapple backdoor interface

2024-11-09 Thread Akihiko Odaki

On 2024/11/08 23:47, Phil Dennis-Jordan wrote:

From: Alexander Graf 

The VMApple machine exposes AUX and ROOT block devices (as well as USB OTG
emulation) via virtio-pci as well as a special, simple backdoor platform
device.

This patch implements this backdoor platform device to the best of my
understanding. I left out any USB OTG parts; they're only needed for
guest recovery and I don't understand the protocol yet.

Signed-off-by: Alexander Graf 
Signed-off-by: Phil Dennis-Jordan 
---

v4:

  * Moved most header code to .c, rest to vmapple.h
  * Better compliance with coding, naming, and formatting conventions.

v8:

  * Replaced uses of cpu_physical_memory_read with dma_memory_read.
  * Replaced an instance of g_free with g_autofree.

  hw/vmapple/Kconfig   |   3 +
  hw/vmapple/bdif.c| 271 +++
  hw/vmapple/meson.build   |   1 +
  hw/vmapple/trace-events  |   5 +
  include/hw/vmapple/vmapple.h |   2 +
  5 files changed, 282 insertions(+)
  create mode 100644 hw/vmapple/bdif.c

diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig
index a73504d5999..68f88876eb9 100644
--- a/hw/vmapple/Kconfig
+++ b/hw/vmapple/Kconfig
@@ -1,3 +1,6 @@
  config VMAPPLE_AES
  bool
  
+config VMAPPLE_BDIF

+bool
+
diff --git a/hw/vmapple/bdif.c b/hw/vmapple/bdif.c
new file mode 100644
index 000..4fa42e4475c
--- /dev/null
+++ b/hw/vmapple/bdif.c
@@ -0,0 +1,271 @@
+/*
+ * VMApple Backdoor Interface
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "hw/vmapple/vmapple.h"
+#include "hw/sysbus.h"
+#include "hw/block/block.h"
+#include "qapi/error.h"
+#include "sysemu/block-backend.h"
+#include "sysemu/dma.h"
+
+OBJECT_DECLARE_SIMPLE_TYPE(VMAppleBdifState, VMAPPLE_BDIF)
+
+struct VMAppleBdifState {
+SysBusDevice parent_obj;
+
+BlockBackend *aux;
+BlockBackend *root;
+MemoryRegion mmio;
+};
+
+#define VMAPPLE_BDIF_SIZE   0x0020
+
+#define REG_DEVID_MASK  0x
+#define DEVID_ROOT  0x
+#define DEVID_AUX   0x0001
+#define DEVID_USB   0x0010
+
+#define REG_STATUS  0x0
+#define REG_STATUS_ACTIVE BIT(0)
+#define REG_CFG 0x4
+#define REG_CFG_ACTIVEBIT(1)
+#define REG_UNK10x8
+#define REG_BUSY0x10
+#define REG_BUSY_READYBIT(0)
+#define REG_UNK20x400
+#define REG_CMD 0x408
+#define REG_NEXT_DEVICE 0x420
+#define REG_UNK30x434
+
+typedef struct VblkSector {
+uint32_t pad;
+uint32_t pad2;
+uint32_t sector;
+uint32_t pad3;
+} VblkSector;
+
+typedef struct VblkReqCmd {
+uint64_t addr;
+uint32_t len;
+uint32_t flags;
+} VblkReqCmd;
+
+typedef struct VblkReq {
+VblkReqCmd sector;
+VblkReqCmd data;
+VblkReqCmd retval;
+} VblkReq;
+
+#define VBLK_DATA_FLAGS_READ  0x00030001
+#define VBLK_DATA_FLAGS_WRITE 0x00010001
+
+#define VBLK_RET_SUCCESS  0
+#define VBLK_RET_FAILED   1
+
+static uint64_t bdif_read(void *opaque, hwaddr offset, unsigned size)
+{
+uint64_t ret = -1;
+uint64_t devid = offset & REG_DEVID_MASK;
+
+switch (offset & ~REG_DEVID_MASK) {
+case REG_STATUS:
+ret = REG_STATUS_ACTIVE;
+break;
+case REG_CFG:
+ret = REG_CFG_ACTIVE;
+break;
+case REG_UNK1:
+ret = 0x420;
+break;
+case REG_BUSY:
+ret = REG_BUSY_READY;
+break;
+case REG_UNK2:
+ret = 0x1;
+break;
+case REG_UNK3:
+ret = 0x0;
+break;
+case REG_NEXT_DEVICE:
+switch (devid) {
+case DEVID_ROOT:
+ret = 0x800;
+break;
+case DEVID_AUX:
+ret = 0x1;
+break;
+}
+break;
+}
+
+trace_bdif_read(offset, size, ret);
+return ret;
+}
+
+static void le2cpu_sector(VblkSector *sector)
+{
+sector->sector = le32_to_cpu(sector->sector);
+}
+
+static void le2cpu_reqcmd(VblkReqCmd *cmd)
+{
+cmd->addr = le64_to_cpu(cmd->addr);
+cmd->len = le32_to_cpu(cmd->len);
+cmd->flags = le32_to_cpu(cmd->flags);
+}
+
+static void le2cpu_req(VblkReq *req)
+{
+le2cpu_reqcmd(&req->sector);
+le2cpu_reqcmd(&req->data);
+le2cpu_reqcmd(&req->retval);
+}
+
+static void vblk_cmd(uint64_t devid, BlockBackend *blk, uint64_t gp_addr,
+ uint64_t static_off)
+{
+VblkReq req;
+VblkSector sector;
+uint64_t off = 0;
+g_autofree char *buf = NULL;
+uint8_t ret = VBLK_RET_FAILED;
+int r;
+MemTxResult dma_result;
+
+dma_result = dma_memory_read(&address_space_memory, gp_addr,
+ 

Re: [PATCH v8 01/15] ui & main loop: Redesign of system-specific main thread event handling

2024-11-09 Thread Phil Dennis-Jordan
On Sun 10. Nov 2024 at 08:01, Akihiko Odaki 
wrote:

> On 2024/11/08 23:46, Phil Dennis-Jordan wrote:
> > macOS's Cocoa event handling must be done on the initial (main) thread
> > of the process. Furthermore, if library or application code uses
> > libdispatch, the main dispatch queue must be handling events on the main
> > thread as well.
> >
> > So far, this has affected Qemu in both the Cocoa and SDL UIs, although
> > in different ways: the Cocoa UI replaces the default qemu_main function
> > with one that spins Qemu's internal main event loop off onto a
> > background thread. SDL (which uses Cocoa internally) on the other hand
> > uses a polling approach within Qemu's main event loop. Events are
> > polled during the SDL UI's dpy_refresh callback, which happens to run
> > on the main thread by default.
>
> GTK should also do the same as SDL and requires treatment; I forgot to
> note that in previous reviews.


Although it‘s possible to build Qemu with GTK support enabled on macOS,
that UI doesn’t actually work on macOS at all, and apparently hasn’t been
supported since 2018, see:
https://stackoverflow.com/a/51474795

I don’t think there’s any point making adjustments to the GTK code by
guessing what might be needed if someone did fix that to work with macOS at
some point.

>

> > As UIs are mutually exclusive, this works OK as long as nothing else
> > needs platform-native event handling. In the next patch, a new device is
> > introduced based on the ParavirtualizedGraphics.framework in macOS.
> > This uses libdispatch internally, and only works when events are being
> > handled on the main runloop. With the current system, it works when
> > using either the Cocoa or the SDL UI. However, it does not when running
> > headless. Moreover, any attempt to install a similar scheme to the
> > Cocoa UI's main thread replacement fails when combined with the SDL
> > UI.
> >
> > This change tidies up main thread management to be more flexible.
> >
> >   * The qemu_main global function pointer is a custom function for the
> > main thread, and it may now be NULL. When it is, the main thread
> > runs the main Qemu loop. This represents the traditional setup.
> >   * When non-null, spawning the main Qemu event loop on a separate
> > thread is now done centrally rather than inside the Cocoa UI code.
> >   * For most platforms, qemu_main is indeed NULL by default, but on
> > Darwin, it defaults to a function that runs the CFRunLoop.
> >   * The Cocoa UI sets qemu_main to a function which runs the
> > NSApplication event handling runloop, as is usual for a Cocoa app.
> >   * The SDL UI overrides the qemu_main function to NULL, thus
> > specifying that Qemu's main loop must run on the main
> > thread.
> >   * For other UIs, or in the absence of UIs, the platform's default
> > behaviour is followed.
> >
> > This means that on macOS, the platform's runloop events are always
> > handled, regardless of chosen UI. The new PV graphics device will
> > thus work in all configurations. There is no functional change on other
> > operating systems.
> >
> > Signed-off-by: Phil Dennis-Jordan 
> > Reviewed-by: Akihiko Odaki 
> > ---
> >
> > v5:
> >
> >   * Simplified the way of setting/clearing the main loop by going back
> > to setting qemu_main directly, but narrowing the scope of what it
> > needs to do, and it can now be NULL.
> >
> > v6:
> >
> >   * Folded function qemu_run_default_main_on_new_thread's code into
> > main()
> >   * Removed whitespace changes left over on lines near code removed
> > between v4 and v5
> >
> >   include/qemu-main.h |  3 +--
> >   include/qemu/typedefs.h |  1 +
> >   system/main.c   | 50 ++
> >   ui/cocoa.m  | 54 ++---
> >   ui/sdl2.c   |  4 +++
> >   5 files changed, 64 insertions(+), 48 deletions(-)
> >
> > diff --git a/include/qemu-main.h b/include/qemu-main.h
> > index 940960a7dbc..4bd0d667edc 100644
> > --- a/include/qemu-main.h
> > +++ b/include/qemu-main.h
> > @@ -5,7 +5,6 @@
> >   #ifndef QEMU_MAIN_H
> >   #define QEMU_MAIN_H
> >
> > -int qemu_default_main(void);
> > -extern int (*qemu_main)(void);
> > +extern qemu_main_fn qemu_main;
> >
> >   #endif /* QEMU_MAIN_H */
> > diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
> > index 3d84efcac47..b02cfe1f328 100644
> > --- a/include/qemu/typedefs.h
> > +++ b/include/qemu/typedefs.h
> > @@ -131,5 +131,6 @@ typedef struct IRQState *qemu_irq;
> >* Function types
> >*/
> >   typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
> > +typedef int (*qemu_main_fn)(void);
> >
> >   #endif /* QEMU_TYPEDEFS_H */
> > diff --git a/system/main.c b/system/main.c
> > index 9b91d21ea8c..d9397a6d5d0 100644
> > --- a/system/main.c
> > +++ b/system/main.c
> > @@ -24,13 +24,14 @@
> >
> >   #include "qemu/osdep.h"
> >   #include "qemu-main.h"
> > +#include "qemu/main-loop.h"
> >   

Re: [PATCH v8 12/15] hw/vmapple/cfg: Introduce vmapple cfg region

2024-11-09 Thread Akihiko Odaki

On 2024/11/08 23:47, Phil Dennis-Jordan wrote:

From: Alexander Graf 

Instead of device tree or other more standardized means, VMApple passes
platform configuration to the first stage boot loader in a binary encoded
format that resides at a dedicated RAM region in physical address space.

This patch models this configuration space as a qdev device which we can
then map at the fixed location in the address space. That way, we can
influence and annotate all configuration fields easily.

Signed-off-by: Alexander Graf 
Signed-off-by: Phil Dennis-Jordan 
---

v3:

  * Replaced legacy device reset method with Resettable method

v4:

  * Fixed initialisation of default values for properties
  * Dropped superfluous endianness conversions
  * Moved most header code to .c, device name #define goes in vmapple.h

v5:

  * Improved error reporting in case of string property buffer overflow.

v7:

  * Changed error messages for overrun of properties with
fixed-length strings to be more useful to users than developers.

v8:

  * Consistent parenthesising of macro arguments for better safety.

  hw/vmapple/Kconfig   |   3 +
  hw/vmapple/cfg.c | 196 +++
  hw/vmapple/meson.build   |   1 +
  include/hw/vmapple/vmapple.h |   2 +
  4 files changed, 202 insertions(+)
  create mode 100644 hw/vmapple/cfg.c

diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig
index 68f88876eb9..8bbeb9a9237 100644
--- a/hw/vmapple/Kconfig
+++ b/hw/vmapple/Kconfig
@@ -4,3 +4,6 @@ config VMAPPLE_AES
  config VMAPPLE_BDIF
  bool
  
+config VMAPPLE_CFG

+bool
+
diff --git a/hw/vmapple/cfg.c b/hw/vmapple/cfg.c
new file mode 100644
index 000..787e2505d57
--- /dev/null
+++ b/hw/vmapple/cfg.c
@@ -0,0 +1,196 @@
+/*
+ * VMApple Configuration Region
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/vmapple/vmapple.h"
+#include "hw/sysbus.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qapi/error.h"
+#include "net/net.h"
+
+OBJECT_DECLARE_SIMPLE_TYPE(VMAppleCfgState, VMAPPLE_CFG)
+
+#define VMAPPLE_CFG_SIZE 0x0001
+
+typedef struct VMAppleCfg {
+uint32_t version; /* 0x000 */
+uint32_t nr_cpus; /* 0x004 */
+uint32_t unk1;/* 0x008 */
+uint32_t unk2;/* 0x00c */
+uint32_t unk3;/* 0x010 */
+uint32_t unk4;/* 0x014 */
+uint64_t ecid;/* 0x018 */
+uint64_t ram_size;/* 0x020 */
+uint32_t run_installer1;  /* 0x028 */
+uint32_t unk5;/* 0x02c */
+uint32_t unk6;/* 0x030 */
+uint32_t run_installer2;  /* 0x034 */
+uint32_t rnd; /* 0x038 */
+uint32_t unk7;/* 0x03c */
+MACAddr mac_en0;  /* 0x040 */
+uint8_t pad1[2];
+MACAddr mac_en1;  /* 0x048 */
+uint8_t pad2[2];
+MACAddr mac_wifi0;/* 0x050 */
+uint8_t pad3[2];
+MACAddr mac_bt0;  /* 0x058 */
+uint8_t pad4[2];
+uint8_t reserved[0xa0];   /* 0x060 */
+uint32_t cpu_ids[0x80];   /* 0x100 */
+uint8_t scratch[0x200];   /* 0x180 */
+char serial[32];  /* 0x380 */
+char unk8[32];/* 0x3a0 */
+char model[32];   /* 0x3c0 */
+uint8_t unk9[32]; /* 0x3e0 */
+uint32_t unk10;   /* 0x400 */
+char soc_name[32];/* 0x404 */
+} VMAppleCfg;
+
+struct VMAppleCfgState {
+SysBusDevice parent_obj;
+VMAppleCfg cfg;
+
+MemoryRegion mem;
+char *serial;
+char *model;
+char *soc_name;
+};
+
+static void vmapple_cfg_reset(Object *obj, ResetType type)
+{
+VMAppleCfgState *s = VMAPPLE_CFG(obj);
+VMAppleCfg *cfg;
+
+cfg = memory_region_get_ram_ptr(&s->mem);
+memset(cfg, 0, VMAPPLE_CFG_SIZE);
+*cfg = s->cfg;
+}
+
+static bool set_fixlen_property_or_error(char *restrict dst,
+ const char *restrict src,
+ size_t dst_size, Error **errp,
+ const char *property_name)
+{
+size_t len;
+
+len = g_strlcpy(dst, src, dst_size);
+if (len < dst_size) { /* len does not count nul terminator */
+return true;
+}
+
+error_setg(errp,
+   "Failed to set property '%s' on VMApple 'cfg' device: length "
+   "(%zu) exceeds maximum of %zu",


Don't print the device name here as it will be automatically printed.


+   property_name, len, dst_size - 1);
+return false;
+}
+
+#define set_fixlen_property_or_return(dst_array, src, errp, property_name) \
+do { \
+if (!set_fixlen_property_or_error((dst_array), (src), \
+  ARRAY_SI

Re: [PATCH v8 10/15] hw/vmapple/aes: Introduce aes engine

2024-11-09 Thread Akihiko Odaki

On 2024/11/08 23:47, Phil Dennis-Jordan wrote:

From: Alexander Graf 

VMApple contains an "aes" engine device that it uses to encrypt and
decrypt its nvram. It has trivial hard coded keys it uses for that
purpose.

Add device emulation for this device model.

Signed-off-by: Alexander Graf 
Signed-off-by: Phil Dennis-Jordan 
---

v3:

  * Rebased on latest upstream and fixed minor breakages.
  * Replaced legacy device reset method with Resettable method

v4:

  * Improved logging of unimplemented functions and guest errors.
  * Better adherence to naming and coding conventions.
  * Cleaner error handling and recovery, including using g_autoptr

v5:

  * More logging improvements
  * Use xxx64_overflow() functions for hexdump buffer size calculations.

v7:

  * Coding style tweaks.

v8:

  * Further improved logging of guest errors.

  hw/vmapple/Kconfig   |   2 +
  hw/vmapple/aes.c | 579 +++
  hw/vmapple/meson.build   |   1 +
  hw/vmapple/trace-events  |  14 +
  include/hw/vmapple/vmapple.h |  17 +
  include/qemu/cutils.h|  15 +
  util/hexdump.c   |  18 ++
  7 files changed, 646 insertions(+)
  create mode 100644 hw/vmapple/aes.c
  create mode 100644 include/hw/vmapple/vmapple.h

diff --git a/hw/vmapple/Kconfig b/hw/vmapple/Kconfig
index 8b137891791..a73504d5999 100644
--- a/hw/vmapple/Kconfig
+++ b/hw/vmapple/Kconfig
@@ -1 +1,3 @@
+config VMAPPLE_AES
+bool
  
diff --git a/hw/vmapple/aes.c b/hw/vmapple/aes.c

new file mode 100644
index 000..43b80bd1561
--- /dev/null
+++ b/hw/vmapple/aes.c
@@ -0,0 +1,579 @@
+/*
+ * QEMU Apple AES device emulation
+ *
+ * Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "trace.h"
+#include "crypto/hash.h"
+#include "crypto/aes.h"
+#include "crypto/cipher.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/vmapple/vmapple.h"
+#include "migration/vmstate.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "sysemu/dma.h"
+
+OBJECT_DECLARE_SIMPLE_TYPE(AESState, APPLE_AES)
+
+#define MAX_FIFO_SIZE 9
+
+#define CMD_KEY   0x1
+#define CMD_KEY_CONTEXT_SHIFT27
+#define CMD_KEY_CONTEXT_MASK (0x1 << CMD_KEY_CONTEXT_SHIFT)
+#define CMD_KEY_SELECT_MAX_IDX   0x7
+#define CMD_KEY_SELECT_SHIFT 24
+#define CMD_KEY_SELECT_MASK  (CMD_KEY_SELECT_MAX_IDX << 
CMD_KEY_SELECT_SHIFT)
+#define CMD_KEY_KEY_LEN_NUM  4u
+#define CMD_KEY_KEY_LEN_SHIFT22
+#define CMD_KEY_KEY_LEN_MASK ((CMD_KEY_KEY_LEN_NUM - 1u) << 
CMD_KEY_KEY_LEN_SHIFT)
+#define CMD_KEY_ENCRYPT_SHIFT20
+#define CMD_KEY_ENCRYPT_MASK (0x1 << CMD_KEY_ENCRYPT_SHIFT)
+#define CMD_KEY_BLOCK_MODE_SHIFT 16
+#define CMD_KEY_BLOCK_MODE_MASK  (0x3 << CMD_KEY_BLOCK_MODE_SHIFT)
+#define CMD_IV0x2
+#define CMD_IV_CONTEXT_SHIFT 26
+#define CMD_IV_CONTEXT_MASK  (0x3 << CMD_KEY_CONTEXT_SHIFT)
+#define CMD_DSB   0x3
+#define CMD_SKG   0x4
+#define CMD_DATA  0x5
+#define CMD_DATA_KEY_CTX_SHIFT   27
+#define CMD_DATA_KEY_CTX_MASK(0x1 << CMD_DATA_KEY_CTX_SHIFT)
+#define CMD_DATA_IV_CTX_SHIFT25
+#define CMD_DATA_IV_CTX_MASK (0x3 << CMD_DATA_IV_CTX_SHIFT)
+#define CMD_DATA_LEN_MASK0xff
+#define CMD_STORE_IV  0x6
+#define CMD_STORE_IV_ADDR_MASK   0xff
+#define CMD_WRITE_REG 0x7
+#define CMD_FLAG  0x8
+#define CMD_FLAG_STOP_MASK   BIT(26)
+#define CMD_FLAG_RAISE_IRQ_MASK  BIT(27)
+#define CMD_FLAG_INFO_MASK   0xff
+#define CMD_MAX   0x10
+
+#define CMD_SHIFT 28
+
+#define REG_STATUS0xc
+#define REG_STATUS_DMA_READ_RUNNING BIT(0)
+#define REG_STATUS_DMA_READ_PENDING BIT(1)
+#define REG_STATUS_DMA_WRITE_RUNNINGBIT(2)
+#define REG_STATUS_DMA_WRITE_PENDINGBIT(3)
+#define REG_STATUS_BUSY BIT(4)
+#define REG_STATUS_EXECUTINGBIT(5)
+#define REG_STATUS_READYBIT(6)
+#define REG_STATUS_TEXT_DPA_SEEDED  BIT(7)
+#define REG_STATUS_UNWRAP_DPA_SEEDEDBIT(8)
+
+#define REG_IRQ_STATUS0x18
+#define REG_IRQ_STATUS_INVALID_CMD  BIT(2)
+#define REG_IRQ_STATUS_FLAG BIT(5)
+#define REG_IRQ_ENABLE0x1c
+#define REG_WATERMARK 0x20
+#define REG_Q_STATUS  0x24
+#define REG_FLAG_INFO 0x30
+#define REG_FIFO  0x200
+
+static const uint32_t key_lens[CMD_KEY_KEY_LEN_NUM] = {
+[0] = 16,
+[1] = 24,
+[2] = 32,
+[3] = 64,
+};
+
+typedef struct Key {
+uint32_t key_len;
+uint8_t key[32];
+} Key;
+
+typedef struct IV {
+uint32_t iv[4];
+} IV;
+
+static Key builtin_keys[CMD_KEY_SELECT_MAX_IDX + 1] = {
+[1] = {
+.key_len = 32,
+.key = { 0x1 },
+},
+[2] = {
+ 

Re: [PATCH v8 01/15] ui & main loop: Redesign of system-specific main thread event handling

2024-11-09 Thread Akihiko Odaki

On 2024/11/10 16:08, Phil Dennis-Jordan wrote:



On Sun 10. Nov 2024 at 08:01, Akihiko Odaki > wrote:


On 2024/11/08 23:46, Phil Dennis-Jordan wrote:
 > macOS's Cocoa event handling must be done on the initial (main)
thread
 > of the process. Furthermore, if library or application code uses
 > libdispatch, the main dispatch queue must be handling events on
the main
 > thread as well.
 >
 > So far, this has affected Qemu in both the Cocoa and SDL UIs,
although
 > in different ways: the Cocoa UI replaces the default qemu_main
function
 > with one that spins Qemu's internal main event loop off onto a
 > background thread. SDL (which uses Cocoa internally) on the other
hand
 > uses a polling approach within Qemu's main event loop. Events are
 > polled during the SDL UI's dpy_refresh callback, which happens to run
 > on the main thread by default.

GTK should also do the same as SDL and requires treatment; I forgot to
note that in previous reviews.


Although it‘s possible to build Qemu with GTK support enabled on macOS, 
that UI doesn’t actually work on macOS at all, and apparently hasn’t 
been supported since 2018, see:

https://stackoverflow.com/a/51474795 

I don’t think there’s any point making adjustments to the GTK code by 
guessing what might be needed if someone did fix that to work with macOS 
at some point.


But there is a GitLab issue saying it "sometimes" crashes, implying it 
works otherwise:

https://gitlab.com/qemu-project/qemu/-/issues/2539



Re: [PATCH v8 15/15] hw/vmapple/vmapple: Add vmapple machine type

2024-11-09 Thread Akihiko Odaki

On 2024/11/08 23:47, Phil Dennis-Jordan wrote:

From: Alexander Graf 

Apple defines a new "vmapple" machine type as part of its proprietary
macOS Virtualization.Framework vmm. This machine type is similar to the
virt one, but with subtle differences in base devices, a few special
vmapple device additions and a vastly different boot chain.

This patch reimplements this machine type in QEMU. To use it, you
have to have a readily installed version of macOS for VMApple,
run on macOS with -accel hvf, pass the Virtualization.Framework
boot rom (AVPBooter) in via -bios, pass the aux and root volume as pflash
and pass aux and root volume as virtio drives. In addition, you also
need to find the machine UUID and pass that as -M vmapple,uuid= parameter:

$ qemu-system-aarch64 -accel hvf -M vmapple,uuid=0x1234 -m 4G \
 -bios 
/System/Library/Frameworks/Virtualization.framework/Versions/A/Resources/AVPBooter.vmapple2.bin
 -drive file=aux,if=pflash,format=raw \
 -drive file=root,if=pflash,format=raw \
 -drive file=aux,if=none,id=aux,format=raw \
 -device vmapple-virtio-aux,drive=aux \
 -drive file=root,if=none,id=root,format=raw \
 -device vmapple-virtio-root,drive=root

With all these in place, you should be able to see macOS booting
successfully.

Known issues:
  - Keyboard and mouse/tablet input is laggy. The reason for this is
either that macOS's XHCI driver is broken when the device/platform
does not support MSI/MSI-X, or there's some unfortunate interplay
with Qemu's XHCI implementation in this scenario.
  - Currently only macOS 12 guests are supported. The boot process for
13+ will need further investigation and adjustment.

Signed-off-by: Alexander Graf 
Co-authored-by: Phil Dennis-Jordan 
Signed-off-by: Phil Dennis-Jordan 
---

v3:
  * Rebased on latest upstream, updated affinity and NIC creation
API usage
  * Included Apple-variant virtio-blk in build dependency
  * Updated API usage for setting 'redist-region-count' array-typed property
on GIC.
  * Switched from virtio HID devices (for which macOS 12 does not contain
drivers) to an XHCI USB controller and USB HID devices.

v4:
  * Fixups for v4 changes to the other patches in the set.
  * Corrected the assert macro to use
  * Removed superfluous endian conversions corresponding to cfg's.
  * Init error handling improvement.
  * No need to select CPU type on TCG, as only HVF is supported.
  * Machine type version bumped to 9.2
  * #include order improved

v5:
  * Fixed memory reservation for ecam alias region.
  * Better error handling setting properties on devices.
  * Simplified the machine ECID/UUID extraction script and actually created a
file for it rather than quoting its code in documentation.

v7:
  * Tiny error handling fix, un-inlined function.

v8:
  * Use object_property_add_uint64_ptr rather than defining custom UUID
property get/set functions.

  MAINTAINERS |   1 +
  contrib/vmapple/uuid.sh |   9 +
  docs/system/arm/vmapple.rst |  60 
  docs/system/target-arm.rst  |   1 +
  hw/vmapple/Kconfig  |  20 ++
  hw/vmapple/meson.build  |   1 +
  hw/vmapple/vmapple.c| 638 
  7 files changed, 730 insertions(+)
  create mode 100755 contrib/vmapple/uuid.sh
  create mode 100644 docs/system/arm/vmapple.rst
  create mode 100644 hw/vmapple/vmapple.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9d0d26cb65f..9591fd44a34 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2767,6 +2767,7 @@ R: Phil Dennis-Jordan 
  S: Maintained
  F: hw/vmapple/*
  F: include/hw/vmapple/*
+F: docs/system/arm/vmapple.rst
  
  Subsystems

  --
diff --git a/contrib/vmapple/uuid.sh b/contrib/vmapple/uuid.sh
new file mode 100755
index 000..956e8c3afed
--- /dev/null
+++ b/contrib/vmapple/uuid.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# Used for converting a guest provisioned using Virtualization.framework
+# for use with the QEMU 'vmapple' aarch64 machine type.
+#
+# Extracts the Machine UUID from Virtualization.framework VM JSON file.
+# (as produced by 'macosvm', passed as command line argument)
+
+plutil -extract machineId raw "$1" | base64 -d | plutil -extract ECID raw -
+
diff --git a/docs/system/arm/vmapple.rst b/docs/system/arm/vmapple.rst
new file mode 100644
index 000..6a634fa4572
--- /dev/null
+++ b/docs/system/arm/vmapple.rst
@@ -0,0 +1,60 @@
+VMApple machine emulation
+
+
+VMApple is the device model that the macOS built-in hypervisor called 
"Virtualization.framework"
+exposes to Apple Silicon macOS guests. The "vmapple" machine model in QEMU 
implements the same
+device model, but does not use any code from Virtualization.Framework.
+
+Prerequisites
+-
+
+To run the vmapple machine model, you need to
+
+ * Run on Apple Silicon
+ * Run on macOS 12.0 or above
+ * Have an already installed copy of a Virtualization.Framework ma

Re: [PATCH v8 02/15] hw/display/apple-gfx: Introduce ParavirtualizedGraphics.Framework support

2024-11-09 Thread Akihiko Odaki

On 2024/11/08 23:46, Phil Dennis-Jordan wrote:

MacOS provides a framework (library) that allows any vmm to implement a
paravirtualized 3d graphics passthrough to the host metal stack called
ParavirtualizedGraphics.Framework (PVG). The library abstracts away
almost every aspect of the paravirtualized device model and only provides
and receives callbacks on MMIO access as well as to share memory address
space between the VM and PVG.

This patch implements a QEMU device that drives PVG for the VMApple
variant of it.

Signed-off-by: Alexander Graf 
Co-authored-by: Alexander Graf 

Subsequent changes:

  * Cherry-pick/rebase conflict fixes, API use updates.
  * Moved from hw/vmapple/ (useful outside that machine type)
  * Overhaul of threading model, many thread safety improvements.
  * Asynchronous rendering.
  * Memory and object lifetime fixes.
  * Refactoring to split generic and (vmapple) MMIO variant specific
code.

Implementation wise, most of the complexity lies in the differing threading
models of ParavirtualizedGraphics.framework, which uses libdispatch and
internal locks, versus QEMU, which heavily uses the BQL, especially during
memory-mapped device I/O. Great care has therefore been taken to prevent
deadlocks by never calling into PVG methods while holding the BQL, and
similarly never acquiring the BQL in a callback from PVG. Different strategies
have been used (libdispatch, blocking and non-blocking BHs, RCU, etc.)
depending on the specific requirements at each framework entry and exit point.

Signed-off-by: Phil Dennis-Jordan 
---

v2:

  * Cherry-pick/rebase conflict fixes
  * BQL function renaming
  * Moved from hw/vmapple/ (useful outside that machine type)
  * Code review comments: Switched to DEFINE_TYPES macro & little endian
MMIO.
  * Removed some dead/superfluous code
  * Mad set_mode thread & memory safe
  * Added migration blocker due to lack of (de-)serialisation.
  * Fixes to ObjC refcounting and autorelease pool usage.
  * Fixed ObjC new/init misuse
  * Switched to ObjC category extension for private property.
  * Simplified task memory mapping and made it thread safe.
  * Refactoring to split generic and vmapple MMIO variant specific
code.
  * Switched to asynchronous MMIO writes on x86-64
  * Rendering and graphics update are now done asynchronously
  * Fixed cursor handling
  * Coding convention fixes
  * Removed software cursor compositing

v3:

  * Rebased on latest upstream, fixed breakages including switching to 
Resettable methods.
  * Squashed patches dealing with dGPUs, MMIO area size, and GPU picking.
  * Allow re-entrant MMIO; this simplifies the code and solves the divergence
between x86-64 and arm64 variants.

v4:

  * Renamed '-vmapple' device variant to '-mmio'
  * MMIO device type now requires aarch64 host and guest
  * Complete overhaul of the glue code for making Qemu's and
ParavirtualizedGraphics.framework's threading and synchronisation models
work together. Calls into PVG are from dispatch queues while the
BQL-holding initiating thread processes AIO context events; callbacks from
PVG are scheduled as BHs on the BQL/main AIO context, awaiting completion
where necessary.
  * Guest frame rendering state is covered by the BQL, with only the PVG calls
outside the lock, and serialised on the named render_queue.
  * Simplified logic for dropping frames in-flight during mode changes, fixed
bug in pending frames logic.
  * Addressed smaller code review notes such as: function naming, object type
declarations, type names/declarations/casts, code formatting, #include
order, over-cautious ObjC retain/release, what goes in init vs realize,
etc.

v5:

  * Smaller non-functional fixes in response to review comments, such as using
NULL for the AIO_WAIT_WHILE context argument, type name formatting,
deleting leftover debug code, logging improvements, state struct field
order and documentation improvements, etc.
  * Instead of a single condition variable for all synchronous BH job types,
there is now one for each callback block. This reduces the number
of threads being awoken unnecessarily to near zero.
  * MMIO device variant: Unified the BH job for raising interrupts.
  * Use DMA APIs for PVG framework's guest memory read requests.
  * Thread safety improvements: ensure mutable AppleGFXState fields are not
accessed outside the appropriate lock. Added dedicated mutex for the task
list.
  * Retain references to MemoryRegions for which there exist mappings in each
PGTask, and for IOSurface mappings.

v6:

  * Switched PGTask_s's' mapped_regions from GPtrArray to GArray
  * Allow DisplaySurface to manage its own vram now that texture -> vram copy
occurs under BQL.
  * Memory mapping operations now use RCU_READ_LOCK_GUARD() where possible
instead of a heavy-weight BH job to acquire the BQL.
  * Changed PVG cursor and mode setting callbacks to kick off BHs instead of
libdispatch tasks