Skip to content

Commit b21f17c

Browse files
pmjphilmd
authored andcommitted
hw/display/apple-gfx: Adds PCI implementation
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 <[email protected]> Reviewed-by: Akihiko Odaki <[email protected]> Message-ID: <[email protected]> Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
1 parent 2352159 commit b21f17c

File tree

4 files changed

+157
-0
lines changed

4 files changed

+157
-0
lines changed

hw/display/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,7 @@ config MAC_PVG_MMIO
149149
bool
150150
depends on MAC_PVG && AARCH64
151151

152+
config MAC_PVG_PCI
153+
bool
154+
depends on MAC_PVG && PCI
155+
default y if PCI_DEVICES

hw/display/apple-gfx-pci.m

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* QEMU Apple ParavirtualizedGraphics.framework device, PCI variant
3+
*
4+
* Copyright © 2023-2024 Phil Dennis-Jordan
5+
*
6+
* SPDX-License-Identifier: GPL-2.0-or-later
7+
*
8+
* ParavirtualizedGraphics.framework is a set of libraries that macOS provides
9+
* which implements 3d graphics passthrough to the host as well as a
10+
* proprietary guest communication channel to drive it. This device model
11+
* implements support to drive that library from within QEMU as a PCI device
12+
* aimed primarily at x86-64 macOS VMs.
13+
*/
14+
15+
#include "qemu/osdep.h"
16+
#include "hw/pci/pci_device.h"
17+
#include "hw/pci/msi.h"
18+
#include "apple-gfx.h"
19+
#include "trace.h"
20+
21+
#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
22+
23+
OBJECT_DECLARE_SIMPLE_TYPE(AppleGFXPCIState, APPLE_GFX_PCI)
24+
25+
struct AppleGFXPCIState {
26+
PCIDevice parent_obj;
27+
28+
AppleGFXState common;
29+
};
30+
31+
static const char *apple_gfx_pci_option_rom_path = NULL;
32+
33+
static void apple_gfx_init_option_rom_path(void)
34+
{
35+
NSURL *option_rom_url = PGCopyOptionROMURL();
36+
const char *option_rom_path = option_rom_url.fileSystemRepresentation;
37+
apple_gfx_pci_option_rom_path = g_strdup(option_rom_path);
38+
[option_rom_url release];
39+
}
40+
41+
static void apple_gfx_pci_init(Object *obj)
42+
{
43+
AppleGFXPCIState *s = APPLE_GFX_PCI(obj);
44+
45+
if (!apple_gfx_pci_option_rom_path) {
46+
/*
47+
* The following is done on device not class init to avoid running
48+
* ObjC code before fork() in -daemonize mode.
49+
*/
50+
PCIDeviceClass *pci = PCI_DEVICE_CLASS(object_get_class(obj));
51+
apple_gfx_init_option_rom_path();
52+
pci->romfile = apple_gfx_pci_option_rom_path;
53+
}
54+
55+
apple_gfx_common_init(obj, &s->common, TYPE_APPLE_GFX_PCI);
56+
}
57+
58+
typedef struct AppleGFXPCIInterruptJob {
59+
PCIDevice *device;
60+
uint32_t vector;
61+
} AppleGFXPCIInterruptJob;
62+
63+
static void apple_gfx_pci_raise_interrupt(void *opaque)
64+
{
65+
AppleGFXPCIInterruptJob *job = opaque;
66+
67+
if (msi_enabled(job->device)) {
68+
msi_notify(job->device, job->vector);
69+
}
70+
g_free(job);
71+
}
72+
73+
static void apple_gfx_pci_interrupt(PCIDevice *dev, uint32_t vector)
74+
{
75+
AppleGFXPCIInterruptJob *job;
76+
77+
trace_apple_gfx_raise_irq(vector);
78+
job = g_malloc0(sizeof(*job));
79+
job->device = dev;
80+
job->vector = vector;
81+
aio_bh_schedule_oneshot(qemu_get_aio_context(),
82+
apple_gfx_pci_raise_interrupt, job);
83+
}
84+
85+
static void apple_gfx_pci_realize(PCIDevice *dev, Error **errp)
86+
{
87+
AppleGFXPCIState *s = APPLE_GFX_PCI(dev);
88+
int ret;
89+
90+
pci_register_bar(dev, PG_PCI_BAR_MMIO,
91+
PCI_BASE_ADDRESS_SPACE_MEMORY, &s->common.iomem_gfx);
92+
93+
ret = msi_init(dev, 0x0 /* config offset; 0 = find space */,
94+
PG_PCI_MAX_MSI_VECTORS, true /* msi64bit */,
95+
false /* msi_per_vector_mask */, errp);
96+
if (ret != 0) {
97+
return;
98+
}
99+
100+
@autoreleasepool {
101+
PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
102+
desc.raiseInterrupt = ^(uint32_t vector) {
103+
apple_gfx_pci_interrupt(dev, vector);
104+
};
105+
106+
apple_gfx_common_realize(&s->common, DEVICE(dev), desc, errp);
107+
[desc release];
108+
desc = nil;
109+
}
110+
}
111+
112+
static void apple_gfx_pci_reset(Object *obj, ResetType type)
113+
{
114+
AppleGFXPCIState *s = APPLE_GFX_PCI(obj);
115+
[s->common.pgdev reset];
116+
}
117+
118+
static void apple_gfx_pci_class_init(ObjectClass *klass, void *data)
119+
{
120+
DeviceClass *dc = DEVICE_CLASS(klass);
121+
PCIDeviceClass *pci = PCI_DEVICE_CLASS(klass);
122+
ResettableClass *rc = RESETTABLE_CLASS(klass);
123+
124+
rc->phases.hold = apple_gfx_pci_reset;
125+
dc->desc = "macOS Paravirtualized Graphics PCI Display Controller";
126+
dc->hotpluggable = false;
127+
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
128+
129+
pci->vendor_id = PG_PCI_VENDOR_ID;
130+
pci->device_id = PG_PCI_DEVICE_ID;
131+
pci->class_id = PCI_CLASS_DISPLAY_OTHER;
132+
pci->realize = apple_gfx_pci_realize;
133+
134+
/* TODO: Property for setting mode list */
135+
}
136+
137+
static const TypeInfo apple_gfx_pci_types[] = {
138+
{
139+
.name = TYPE_APPLE_GFX_PCI,
140+
.parent = TYPE_PCI_DEVICE,
141+
.instance_size = sizeof(AppleGFXPCIState),
142+
.class_init = apple_gfx_pci_class_init,
143+
.instance_init = apple_gfx_pci_init,
144+
.interfaces = (InterfaceInfo[]) {
145+
{ INTERFACE_PCIE_DEVICE },
146+
{ },
147+
},
148+
}
149+
};
150+
DEFINE_TYPES(apple_gfx_pci_types)
151+

hw/display/apple-gfx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "ui/surface.h"
1515

1616
#define TYPE_APPLE_GFX_MMIO "apple-gfx-mmio"
17+
#define TYPE_APPLE_GFX_PCI "apple-gfx-pci"
1718

1819
@class PGDeviceDescriptor;
1920
@protocol PGDevice;

hw/display/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ system_ss.add(when: 'CONFIG_ATI_VGA', if_true: [files('ati.c', 'ati_2d.c', 'ati_
6363

6464
if host_os == 'darwin'
6565
system_ss.add(when: 'CONFIG_MAC_PVG', if_true: [files('apple-gfx.m'), pvg, metal])
66+
system_ss.add(when: 'CONFIG_MAC_PVG_PCI', if_true: [files('apple-gfx-pci.m'), pvg, metal])
6667
if cpu == 'aarch64'
6768
system_ss.add(when: 'CONFIG_MAC_PVG_MMIO', if_true: [files('apple-gfx-mmio.m'), pvg, metal])
6869
endif

0 commit comments

Comments
 (0)