> + s->pgdev = PGNewDeviceWithDescriptor(desc);
> +
> + disp_desc = apple_gfx_prepare_display_descriptor(s);
> + s->pgdisp = [s->pgdev newDisplayWithDescriptor:disp_desc
> + port:0 serialNum:1234];
port has a fixed number, but I don't think there is anything that
prevents plugging multiple apple-gfx devices.
The port number is PGDevice instance specific, so 0 is safe here. I've actually now tested with 2 apple-gfx-pci devices, and it's technically possible and the guest picks them both up. But it's actually the serial number that ends up being a problem, because macOS ignores "duplicate" displays with identical vendor/product/serial number tuples.
So I suggest a static integer variable for the display serial number that we initialise to 1 and increment every time an apple-gfx device is realized.
> + [disp_desc release];
> + s->pgdisp.modeList = apple_gfx_prepare_display_mode_array();
> +
> + s->con = graphic_console_init(dev, 0, &apple_gfx_fb_ops, s);
> + return true;
> +}
> diff --git a/hw/display/meson.build b/hw/display/meson.build
> index 20a94973fa2..cf9e6dd35d2 100644
> --- a/hw/display/meson.build
> +++ b/hw/display/meson.build
> @@ -61,6 +61,12 @@ system_ss.add(when: 'CONFIG_ARTIST', if_true: files('artist.c'))
>
> system_ss.add(when: 'CONFIG_ATI_VGA', if_true: [files('ati.c', 'ati_2d.c', 'ati_dbg.c'), pixman])
>
> +if host_os == 'darwin'
> + system_ss.add(when: 'CONFIG_MAC_PVG', if_true: [files('apple-gfx.m'), pvg, metal])
> + if cpu == 'aarch64'
> + system_ss.add(when: 'CONFIG_MAC_PVG_MMIO', if_true: [files('apple-gfx-mmio.m'), pvg, metal])
> + endif
> +endif
>
> if config_all_devices.has_key('CONFIG_VIRTIO_GPU')
> virtio_gpu_ss = ss.source_set()
> diff --git a/hw/display/trace-events b/hw/display/trace-events
> index d26d663f963..a50e4eea0c0 100644
> --- a/hw/display/trace-events
> +++ b/hw/display/trace-events
> @@ -194,3 +194,31 @@ dm163_bits_ppi(unsigned dest_width) "dest_width : %u"
> dm163_leds(int led, uint32_t value) "led %d: 0x%x"
> dm163_channels(int channel, uint8_t value) "channel %d: 0x%x"
> dm163_refresh_rate(uint32_t rr) "refresh rate %d"
> +
> +# apple-gfx.m
> +apple_gfx_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
> +apple_gfx_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64
> +apple_gfx_create_task(uint32_t vm_size, void *va) "vm_size=0x%x base_addr=%p"
> +apple_gfx_destroy_task(void *task, unsigned int num_mapped_regions) "task=%p, task->mapped_regions->len=%u"
> +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"
> +apple_gfx_map_memory_range(uint32_t i, uint64_t phys_addr, uint64_t phys_len) "[%d] phys_addr=0x%"PRIx64" phys_len=0x%"PRIx64
> +apple_gfx_remap(uint64_t retval, void *source_ptr, uint64_t target) "retval=%"PRId64" source=%p target=0x%"PRIx64
> +apple_gfx_unmap_memory(void *task, uint64_t virtual_offset, uint64_t length) "task=%p virtual_offset=0x%"PRIx64" length=0x%"PRIx64
> +apple_gfx_read_memory(uint64_t phys_address, uint64_t length, void *dst) "phys_addr=0x%"PRIx64" length=0x%"PRIx64" dest=%p"
> +apple_gfx_raise_irq(uint32_t vector) "vector=0x%x"
> +apple_gfx_new_frame(void) ""
> +apple_gfx_mode_change(uint64_t x, uint64_t y) "x=%"PRId64" y=%"PRId64
> +apple_gfx_cursor_set(uint32_t bpp, uint64_t width, uint64_t height) "bpp=%d width=%"PRId64" height=0x%"PRId64
> +apple_gfx_cursor_show(uint32_t show) "show=%d"
> +apple_gfx_cursor_move(void) ""
> +apple_gfx_common_init(const char *device_name, size_t mmio_size) "device: %s; MMIO size: %zu bytes"
> +
> +# apple-gfx-mmio.m
> +apple_gfx_mmio_iosfc_read(uint64_t offset, uint64_t res) "offset=0x%"PRIx64" res=0x%"PRIx64
> +apple_gfx_mmio_iosfc_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx64
> +apple_gfx_iosfc_map_memory(uint64_t phys, uint64_t len, uint32_t ro, void *va, void *e, void *f, void* va_result) "phys=0x%"PRIx64" len=0x%"PRIx64" ro=%d va=%p e=%p f=%p -> *va=%p"
> +apple_gfx_iosfc_map_memory_new_region(size_t i, void *region, uint64_t start, uint64_t end) "index=%zu, region=%p, 0x%"PRIx64"-0x%"PRIx64
> +apple_gfx_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"
> +apple_gfx_iosfc_unmap_memory_region(void* mem, void *region) "unmapping @ %p from memory region %p"
> +apple_gfx_iosfc_raise_irq(uint32_t vector) "vector=0x%x"
> +
> diff --git a/meson.build b/meson.build
> index e0b880e4e13..3c61238bc77 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -794,6 +794,8 @@ socket = []
> version_res = []
> coref = []
> iokit = []
> +pvg = not_found
> +metal = []
> emulator_link_args = []
> midl = not_found
> widl = not_found
> @@ -815,6 +817,8 @@ elif host_os == 'darwin'
> coref = dependency('appleframeworks', modules: 'CoreFoundation')
> iokit = dependency('appleframeworks', modules: 'IOKit', required: false)
> host_dsosuf = '.dylib'
> + pvg = dependency('appleframeworks', modules: 'ParavirtualizedGraphics')
> + metal = dependency('appleframeworks', modules: 'Metal')
> elif host_os == 'sunos'
> socket = [cc.find_library('socket'),
> cc.find_library('nsl'),