mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'hw-misc-20241231' of https://github.com/philmd/qemu into staging
Misc HW patches queue - Allow more than 4 legacy IRQs on Generic PCI Express Bridge (Alexander) - Add MMIO-based Inter-VM shared memory device 'ivshmem-flat' (Gustavo) - Use UHCI register definitions (Guenter) - Propagate CPU endianness to microblaze_load_kernel (Philippe) - Mark x86/TriCore devices as little-endian, OpenRISC/SPARC as big (Philippe) - Don't set callback_opaque NULL in fw_cfg_modify_bytes_read (Shameer) - Simplify non-KVM checks on AMD IOMMU XTSup feature (Philippe) - Trivial cleanups on xilinx_ethlite, vmcoreinfo, qxl (Philippe, Hyman) - Move USB-HCD-XHCI msi/msix properties from NEC to superclass (Phil) - Redesign of main thread event handling due to macOS Cocoa (Phil) - Introduce ParavirtualizedGraphics.Framework support 'apple-gfx' (Phil) - Pad short Ethernet frames on macOS vmnet (William) # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmd0Ul0ACgkQ4+MsLN6t # wN7sCA/9HFWahKYW+6Y+gHfLPvJzkIqC5mwfQAUY7GsrNVFdIpUjK9ln9xUEqCQz # DkVxoZQcP++d8cnnl17wXHsRcavyDDadGU5/161eNC7fbKbLRAslObz/dtExxDn2 # sctx9HMcbLl1UMFPqi/Pbt8NEZr0iOLzDDl+nRuOK8QRFnd2zGm1lF1oHeyja3t1 # flnQKI9YD0U/+0RVNR2FOpUam2Fu1EuQEPp0jMwkmcoyoNLwCXrP9XyRybVZnzgM # cFm9fYbVlwjsVia+Bsk3CmHX5Gna/1bS3CL8Y9gUScYYwYU5VDAA8Fvv4gPsa4+u # WSyttL2qCFdgF75S5FoAvEQzYFBcw25eFf8jJhbEn4I6MuQew8lww5OZEyvE8rag # 2hg3nc4W0x76mLunqrNm+h+Z3vqd/amFcd9YNZjpzxQK//TwvOAQTWi31VtWa4OF # F1qdv78tQKkRY7noq8WkcL/io6D7iE/BMx/XIOF8uPf8BLIBMvPDnDABjaB/yLkS # Q/e+/monxkhknDY6K9xkVei7rn6c0LkuLzKxVzEzVKPVzM8N0JAl/1KaNVO8fxjJ # kLvfGP/RdYOZqG4dNi8W3PhV/+UZz1FS3L1MpI4NXQ59br57BbVQP9ARGO6WpPWn # O9zIJOAqdzcWU0aULIsvQA3nC1iJnFHEovq0bl8qBbY51k26Lg0= # =AL3L # -----END PGP SIGNATURE----- # gpg: Signature made Tue 31 Dec 2024 15:21:49 EST # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full] # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * tag 'hw-misc-20241231' of https://github.com/philmd/qemu: (29 commits) hw/display/qxl: Do not use C99 // comments net/vmnet: Pad short Ethernet frames MAINTAINERS: Add myself as maintainer for apple-gfx, reviewer for HVF hw/display/apple-gfx: Adds configurable mode list hw/display/apple-gfx: Adds PCI implementation hw/display/apple-gfx: Introduce ParavirtualizedGraphics.Framework support ui & main loop: Redesign of system-specific main thread event handling hw/usb/hcd-xhci: Unimplemented/guest error logging for port MMIO hw/usb/hcd-xhci-pci: Move msi/msix properties from NEC to superclass hw/block/virtio-blk: Replaces request free function with g_free hw/i386/amd_iommu: Simplify non-KVM checks on XTSup feature hw/misc/vmcoreinfo: Rename opaque pointer as 'opaque' hw/misc/vmcoreinfo: Declare QOM type using DEFINE_TYPES macro fw_cfg: Don't set callback_opaque NULL in fw_cfg_modify_bytes_read() hw/net/xilinx_ethlite: Rename rxbuf -> port_index hw/net/xilinx_ethlite: Correct maximum RX buffer size hw/net/xilinx_ethlite: Update QOM style hw/net/xilinx_ethlite: Remove unuseful debug logs hw/net/xilinx_ethlite: Convert some debug logs to trace events hw/sparc: Mark devices as big-endian ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -509,6 +509,7 @@ F: target/arm/hvf/
|
||||
X86 HVF CPUs
|
||||
M: Cameron Esfahani <dirty@apple.com>
|
||||
M: Roman Bolshakov <rbolshakov@ddn.com>
|
||||
R: Phil Dennis-Jordan <phil@philjordan.eu>
|
||||
W: https://wiki.qemu.org/Features/HVF
|
||||
S: Maintained
|
||||
F: target/i386/hvf/
|
||||
@@ -516,6 +517,7 @@ F: target/i386/hvf/
|
||||
HVF
|
||||
M: Cameron Esfahani <dirty@apple.com>
|
||||
M: Roman Bolshakov <rbolshakov@ddn.com>
|
||||
R: Phil Dennis-Jordan <phil@philjordan.eu>
|
||||
W: https://wiki.qemu.org/Features/HVF
|
||||
S: Maintained
|
||||
F: accel/hvf/
|
||||
@@ -2631,6 +2633,11 @@ F: hw/display/edid*
|
||||
F: include/hw/display/edid.h
|
||||
F: qemu-edid.c
|
||||
|
||||
macOS PV Graphics (apple-gfx)
|
||||
M: Phil Dennis-Jordan <phil@philjordan.eu>
|
||||
S: Maintained
|
||||
F: hw/display/apple-gfx*
|
||||
|
||||
PIIX4 South Bridge (i82371AB)
|
||||
M: Hervé Poussineau <hpoussin@reactos.org>
|
||||
M: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
|
||||
@@ -86,6 +86,7 @@ Emulated Devices
|
||||
devices/ccid.rst
|
||||
devices/cxl.rst
|
||||
devices/ivshmem.rst
|
||||
devices/ivshmem-flat.rst
|
||||
devices/keyboard.rst
|
||||
devices/net.rst
|
||||
devices/nvme.rst
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
Inter-VM Shared Memory Flat Device
|
||||
----------------------------------
|
||||
|
||||
The ivshmem-flat device is meant to be used on machines that lack a PCI bus,
|
||||
making them unsuitable for the use of the traditional ivshmem device modeled as
|
||||
a PCI device. Machines like those with a Cortex-M MCU are good candidates to use
|
||||
the ivshmem-flat device. Also, since the flat version maps the control and
|
||||
status registers directly to the memory, it requires a quite tiny "device
|
||||
driver" to interact with other VMs, which is useful in some RTOSes, like
|
||||
Zephyr, which usually run on constrained resource targets.
|
||||
|
||||
Similar to the ivshmem device, the ivshmem-flat device supports both peer
|
||||
notification via HW interrupts and Inter-VM shared memory. This allows the
|
||||
device to be used together with the traditional ivshmem, enabling communication
|
||||
between, for instance, an aarch64 VM (using the traditional ivshmem device and
|
||||
running Linux), and an arm VM (using the ivshmem-flat device and running Zephyr
|
||||
instead).
|
||||
|
||||
The ivshmem-flat device does not support the use of a ``memdev`` option (see
|
||||
ivshmem.rst for more details). It relies on the ivshmem server to create and
|
||||
distribute the proper shared memory file descriptor and the eventfd(s) to notify
|
||||
(interrupt) the peers. Therefore, to use this device, it is always necessary to
|
||||
have an ivshmem server up and running for proper device creation.
|
||||
|
||||
Although the ivshmem-flat supports both peer notification (interrupts) and
|
||||
shared memory, the interrupt mechanism is optional. If no input IRQ is
|
||||
specified for the device it is disabled, preventing the VM from notifying or
|
||||
being notified by other VMs (a warning will be displayed to the user to inform
|
||||
the IRQ mechanism is disabled). The shared memory region is always present.
|
||||
|
||||
The MMRs (INTRMASK, INTRSTATUS, IVPOSITION, and DOORBELL registers) offsets at
|
||||
the MMR region, and their functions, follow the ivshmem spec, so they work
|
||||
exactly as in the ivshmem PCI device (see ./specs/ivshmem-spec.txt).
|
||||
+1
-1
@@ -673,7 +673,7 @@ static void create_pcie(SBSAMachineState *sms)
|
||||
/* Map IO port space */
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
|
||||
|
||||
for (i = 0; i < GPEX_NUM_IRQS; i++) {
|
||||
for (i = 0; i < PCI_NUM_PINS; i++) {
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
|
||||
qdev_get_gpio_in(sms->gic, irq + i));
|
||||
gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
|
||||
|
||||
+1
-1
@@ -1547,7 +1547,7 @@ static void create_pcie(VirtMachineState *vms)
|
||||
/* Map IO port space */
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio);
|
||||
|
||||
for (i = 0; i < GPEX_NUM_IRQS; i++) {
|
||||
for (i = 0; i < PCI_NUM_PINS; i++) {
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
|
||||
qdev_get_gpio_in(vms->gic, irq + i));
|
||||
gpex_set_irq_num(GPEX_HOST(dev), i, irq + i);
|
||||
|
||||
+19
-24
@@ -50,11 +50,6 @@ static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq,
|
||||
req->mr_next = NULL;
|
||||
}
|
||||
|
||||
static void virtio_blk_free_request(VirtIOBlockReq *req)
|
||||
{
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
|
||||
{
|
||||
VirtIOBlock *s = req->dev;
|
||||
@@ -93,7 +88,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
|
||||
if (acct_failed) {
|
||||
block_acct_failed(blk_get_stats(s->blk), &req->acct);
|
||||
}
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
blk_error_action(s->blk, action, is_read, error);
|
||||
@@ -136,7 +131,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
|
||||
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
|
||||
block_acct_done(blk_get_stats(s->blk), &req->acct);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +146,7 @@ static void virtio_blk_flush_complete(void *opaque, int ret)
|
||||
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
|
||||
block_acct_done(blk_get_stats(s->blk), &req->acct);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret)
|
||||
@@ -169,7 +164,7 @@ static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret)
|
||||
if (is_write_zeroes) {
|
||||
block_acct_done(blk_get_stats(s->blk), &req->acct);
|
||||
}
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s, VirtQueue *vq)
|
||||
@@ -214,7 +209,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
|
||||
fail:
|
||||
virtio_blk_req_complete(req, status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
static inline void submit_requests(VirtIOBlock *s, MultiReqBuffer *mrb,
|
||||
@@ -612,7 +607,7 @@ static void virtio_blk_zone_report_complete(void *opaque, int ret)
|
||||
|
||||
out:
|
||||
virtio_blk_req_complete(req, err_status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
g_free(data->zone_report_data.zones);
|
||||
g_free(data);
|
||||
}
|
||||
@@ -661,7 +656,7 @@ static void virtio_blk_handle_zone_report(VirtIOBlockReq *req,
|
||||
return;
|
||||
out:
|
||||
virtio_blk_req_complete(req, err_status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
static void virtio_blk_zone_mgmt_complete(void *opaque, int ret)
|
||||
@@ -677,7 +672,7 @@ static void virtio_blk_zone_mgmt_complete(void *opaque, int ret)
|
||||
}
|
||||
|
||||
virtio_blk_req_complete(req, err_status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
static int virtio_blk_handle_zone_mgmt(VirtIOBlockReq *req, BlockZoneOp op)
|
||||
@@ -719,7 +714,7 @@ static int virtio_blk_handle_zone_mgmt(VirtIOBlockReq *req, BlockZoneOp op)
|
||||
return 0;
|
||||
out:
|
||||
virtio_blk_req_complete(req, err_status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
return err_status;
|
||||
}
|
||||
|
||||
@@ -750,7 +745,7 @@ static void virtio_blk_zone_append_complete(void *opaque, int ret)
|
||||
|
||||
out:
|
||||
virtio_blk_req_complete(req, err_status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
g_free(data);
|
||||
}
|
||||
|
||||
@@ -788,7 +783,7 @@ static int virtio_blk_handle_zone_append(VirtIOBlockReq *req,
|
||||
|
||||
out:
|
||||
virtio_blk_req_complete(req, err_status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
return err_status;
|
||||
}
|
||||
|
||||
@@ -855,7 +850,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
|
||||
block_acct_invalid(blk_get_stats(s->blk),
|
||||
is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -911,7 +906,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
|
||||
VIRTIO_BLK_ID_BYTES));
|
||||
iov_from_buf(in_iov, in_num, 0, serial, size);
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
break;
|
||||
}
|
||||
case VIRTIO_BLK_T_ZONE_APPEND & ~VIRTIO_BLK_T_OUT:
|
||||
@@ -943,7 +938,7 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
|
||||
if (unlikely(!(type & VIRTIO_BLK_T_OUT) ||
|
||||
out_len > sizeof(dwz_hdr))) {
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -960,14 +955,14 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
|
||||
is_write_zeroes);
|
||||
if (err_status != VIRTIO_BLK_S_OK) {
|
||||
virtio_blk_req_complete(req, err_status);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -988,7 +983,7 @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
|
||||
while ((req = virtio_blk_get_request(s, vq))) {
|
||||
if (virtio_blk_handle_request(req, &mrb)) {
|
||||
virtqueue_detach_element(req->vq, &req->elem, 0);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1038,7 +1033,7 @@ static void virtio_blk_dma_restart_bh(void *opaque)
|
||||
while (req) {
|
||||
next = req->next;
|
||||
virtqueue_detach_element(req->vq, &req->elem, 0);
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
req = next;
|
||||
}
|
||||
break;
|
||||
@@ -1121,7 +1116,7 @@ static void virtio_blk_reset(VirtIODevice *vdev)
|
||||
/* No other threads can access req->vq here */
|
||||
virtqueue_detach_element(req->vq, &req->elem, 0);
|
||||
|
||||
virtio_blk_free_request(req);
|
||||
g_free(req);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,3 +140,16 @@ config XLNX_DISPLAYPORT
|
||||
|
||||
config DM163
|
||||
bool
|
||||
|
||||
config MAC_PVG
|
||||
bool
|
||||
default y
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* QEMU Apple ParavirtualizedGraphics.framework device, MMIO (arm64) variant
|
||||
*
|
||||
* Copyright © 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* 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 an MMIO-based
|
||||
* system device for macOS on arm64 VMs.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "block/aio-wait.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/irq.h"
|
||||
#include "apple-gfx.h"
|
||||
#include "trace.h"
|
||||
|
||||
#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(AppleGFXMMIOState, APPLE_GFX_MMIO)
|
||||
|
||||
/*
|
||||
* ParavirtualizedGraphics.Framework only ships header files for the PCI
|
||||
* variant which does not include IOSFC descriptors and host devices. We add
|
||||
* their definitions here so that we can also work with the ARM version.
|
||||
*/
|
||||
typedef bool(^IOSFCRaiseInterrupt)(uint32_t vector);
|
||||
typedef bool(^IOSFCUnmapMemory)(void *, void *, void *, void *, void *, void *);
|
||||
typedef bool(^IOSFCMapMemory)(uint64_t phys, uint64_t len, bool ro, void **va,
|
||||
void *, void *);
|
||||
|
||||
@interface PGDeviceDescriptor (IOSurfaceMapper)
|
||||
@property (readwrite, nonatomic) bool usingIOSurfaceMapper;
|
||||
@end
|
||||
|
||||
@interface PGIOSurfaceHostDeviceDescriptor : NSObject
|
||||
-(PGIOSurfaceHostDeviceDescriptor *)init;
|
||||
@property (readwrite, nonatomic, copy, nullable) IOSFCMapMemory mapMemory;
|
||||
@property (readwrite, nonatomic, copy, nullable) IOSFCUnmapMemory unmapMemory;
|
||||
@property (readwrite, nonatomic, copy, nullable) IOSFCRaiseInterrupt raiseInterrupt;
|
||||
@end
|
||||
|
||||
@interface PGIOSurfaceHostDevice : NSObject
|
||||
-(instancetype)initWithDescriptor:(PGIOSurfaceHostDeviceDescriptor *)desc;
|
||||
-(uint32_t)mmioReadAtOffset:(size_t)offset;
|
||||
-(void)mmioWriteAtOffset:(size_t)offset value:(uint32_t)value;
|
||||
@end
|
||||
|
||||
struct AppleGFXMapSurfaceMemoryJob;
|
||||
struct AppleGFXMMIOState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
AppleGFXState common;
|
||||
|
||||
qemu_irq irq_gfx;
|
||||
qemu_irq irq_iosfc;
|
||||
MemoryRegion iomem_iosfc;
|
||||
PGIOSurfaceHostDevice *pgiosfc;
|
||||
};
|
||||
|
||||
typedef struct AppleGFXMMIOJob {
|
||||
AppleGFXMMIOState *state;
|
||||
uint64_t offset;
|
||||
uint64_t value;
|
||||
bool completed;
|
||||
} AppleGFXMMIOJob;
|
||||
|
||||
static void iosfc_do_read(void *opaque)
|
||||
{
|
||||
AppleGFXMMIOJob *job = opaque;
|
||||
job->value = [job->state->pgiosfc mmioReadAtOffset:job->offset];
|
||||
qatomic_set(&job->completed, true);
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
static uint64_t iosfc_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
AppleGFXMMIOJob job = {
|
||||
.state = opaque,
|
||||
.offset = offset,
|
||||
.completed = false,
|
||||
};
|
||||
dispatch_queue_t queue =
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
|
||||
dispatch_async_f(queue, &job, iosfc_do_read);
|
||||
AIO_WAIT_WHILE(NULL, !qatomic_read(&job.completed));
|
||||
|
||||
trace_apple_gfx_mmio_iosfc_read(offset, job.value);
|
||||
return job.value;
|
||||
}
|
||||
|
||||
static void iosfc_do_write(void *opaque)
|
||||
{
|
||||
AppleGFXMMIOJob *job = opaque;
|
||||
[job->state->pgiosfc mmioWriteAtOffset:job->offset value:job->value];
|
||||
qatomic_set(&job->completed, true);
|
||||
aio_wait_kick();
|
||||
}
|
||||
|
||||
static void iosfc_write(void *opaque, hwaddr offset, uint64_t val,
|
||||
unsigned size)
|
||||
{
|
||||
AppleGFXMMIOJob job = {
|
||||
.state = opaque,
|
||||
.offset = offset,
|
||||
.value = val,
|
||||
.completed = false,
|
||||
};
|
||||
dispatch_queue_t queue =
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
|
||||
dispatch_async_f(queue, &job, iosfc_do_write);
|
||||
AIO_WAIT_WHILE(NULL, !qatomic_read(&job.completed));
|
||||
|
||||
trace_apple_gfx_mmio_iosfc_write(offset, val);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps apple_iosfc_ops = {
|
||||
.read = iosfc_read,
|
||||
.write = iosfc_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 8,
|
||||
},
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 8,
|
||||
},
|
||||
};
|
||||
|
||||
static void raise_irq_bh(void *opaque)
|
||||
{
|
||||
qemu_irq *irq = opaque;
|
||||
|
||||
qemu_irq_pulse(*irq);
|
||||
}
|
||||
|
||||
static void *apple_gfx_mmio_map_surface_memory(uint64_t guest_physical_address,
|
||||
uint64_t length, bool read_only)
|
||||
{
|
||||
void *mem;
|
||||
MemoryRegion *region = NULL;
|
||||
|
||||
RCU_READ_LOCK_GUARD();
|
||||
mem = apple_gfx_host_ptr_for_gpa_range(guest_physical_address,
|
||||
length, read_only, ®ion);
|
||||
if (mem) {
|
||||
memory_region_ref(region);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
static bool apple_gfx_mmio_unmap_surface_memory(void *ptr)
|
||||
{
|
||||
MemoryRegion *region;
|
||||
ram_addr_t offset = 0;
|
||||
|
||||
RCU_READ_LOCK_GUARD();
|
||||
region = memory_region_from_host(ptr, &offset);
|
||||
if (!region) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: memory at %p to be unmapped not found.\n",
|
||||
__func__, ptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
trace_apple_gfx_iosfc_unmap_memory_region(ptr, region);
|
||||
memory_region_unref(region);
|
||||
return true;
|
||||
}
|
||||
|
||||
static PGIOSurfaceHostDevice *apple_gfx_prepare_iosurface_host_device(
|
||||
AppleGFXMMIOState *s)
|
||||
{
|
||||
PGIOSurfaceHostDeviceDescriptor *iosfc_desc =
|
||||
[PGIOSurfaceHostDeviceDescriptor new];
|
||||
PGIOSurfaceHostDevice *iosfc_host_dev;
|
||||
|
||||
iosfc_desc.mapMemory =
|
||||
^bool(uint64_t phys, uint64_t len, bool ro, void **va, void *e, void *f) {
|
||||
*va = apple_gfx_mmio_map_surface_memory(phys, len, ro);
|
||||
|
||||
trace_apple_gfx_iosfc_map_memory(phys, len, ro, va, e, f, *va);
|
||||
|
||||
return *va != NULL;
|
||||
};
|
||||
|
||||
iosfc_desc.unmapMemory =
|
||||
^bool(void *va, void *b, void *c, void *d, void *e, void *f) {
|
||||
return apple_gfx_mmio_unmap_surface_memory(va);
|
||||
};
|
||||
|
||||
iosfc_desc.raiseInterrupt = ^bool(uint32_t vector) {
|
||||
trace_apple_gfx_iosfc_raise_irq(vector);
|
||||
aio_bh_schedule_oneshot(qemu_get_aio_context(),
|
||||
raise_irq_bh, &s->irq_iosfc);
|
||||
return true;
|
||||
};
|
||||
|
||||
iosfc_host_dev =
|
||||
[[PGIOSurfaceHostDevice alloc] initWithDescriptor:iosfc_desc];
|
||||
[iosfc_desc release];
|
||||
return iosfc_host_dev;
|
||||
}
|
||||
|
||||
static void apple_gfx_mmio_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
@autoreleasepool {
|
||||
AppleGFXMMIOState *s = APPLE_GFX_MMIO(dev);
|
||||
PGDeviceDescriptor *desc = [PGDeviceDescriptor new];
|
||||
|
||||
desc.raiseInterrupt = ^(uint32_t vector) {
|
||||
trace_apple_gfx_raise_irq(vector);
|
||||
aio_bh_schedule_oneshot(qemu_get_aio_context(),
|
||||
raise_irq_bh, &s->irq_gfx);
|
||||
};
|
||||
|
||||
desc.usingIOSurfaceMapper = true;
|
||||
s->pgiosfc = apple_gfx_prepare_iosurface_host_device(s);
|
||||
|
||||
if (!apple_gfx_common_realize(&s->common, dev, desc, errp)) {
|
||||
[s->pgiosfc release];
|
||||
s->pgiosfc = nil;
|
||||
}
|
||||
|
||||
[desc release];
|
||||
desc = nil;
|
||||
}
|
||||
}
|
||||
|
||||
static void apple_gfx_mmio_init(Object *obj)
|
||||
{
|
||||
AppleGFXMMIOState *s = APPLE_GFX_MMIO(obj);
|
||||
|
||||
apple_gfx_common_init(obj, &s->common, TYPE_APPLE_GFX_MMIO);
|
||||
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->common.iomem_gfx);
|
||||
memory_region_init_io(&s->iomem_iosfc, obj, &apple_iosfc_ops, s,
|
||||
TYPE_APPLE_GFX_MMIO, 0x10000);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem_iosfc);
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq_gfx);
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq_iosfc);
|
||||
}
|
||||
|
||||
static void apple_gfx_mmio_reset(Object *obj, ResetType type)
|
||||
{
|
||||
AppleGFXMMIOState *s = APPLE_GFX_MMIO(obj);
|
||||
[s->common.pgdev reset];
|
||||
}
|
||||
|
||||
static const Property apple_gfx_mmio_properties[] = {
|
||||
DEFINE_PROP_ARRAY("display-modes", AppleGFXMMIOState,
|
||||
common.num_display_modes, common.display_modes,
|
||||
qdev_prop_apple_gfx_display_mode, AppleGFXDisplayMode),
|
||||
};
|
||||
|
||||
static void apple_gfx_mmio_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||
|
||||
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 const TypeInfo apple_gfx_mmio_types[] = {
|
||||
{
|
||||
.name = TYPE_APPLE_GFX_MMIO,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AppleGFXMMIOState),
|
||||
.class_init = apple_gfx_mmio_class_init,
|
||||
.instance_init = apple_gfx_mmio_init,
|
||||
}
|
||||
};
|
||||
DEFINE_TYPES(apple_gfx_mmio_types)
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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 "qemu/osdep.h"
|
||||
#include "hw/pci/pci_device.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "apple-gfx.h"
|
||||
#include "trace.h"
|
||||
|
||||
#import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
|
||||
|
||||
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);
|
||||
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, DEVICE(dev), 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 const Property apple_gfx_pci_properties[] = {
|
||||
DEFINE_PROP_ARRAY("display-modes", AppleGFXPCIState,
|
||||
common.num_display_modes, common.display_modes,
|
||||
qdev_prop_apple_gfx_display_mode, AppleGFXDisplayMode),
|
||||
};
|
||||
|
||||
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 = apple_gfx_pci_reset;
|
||||
dc->desc = "macOS Paravirtualized Graphics PCI Display Controller";
|
||||
dc->hotpluggable = false;
|
||||
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
||||
|
||||
pci->vendor_id = PG_PCI_VENDOR_ID;
|
||||
pci->device_id = PG_PCI_DEVICE_ID;
|
||||
pci->class_id = PCI_CLASS_DISPLAY_OTHER;
|
||||
pci->realize = apple_gfx_pci_realize;
|
||||
|
||||
device_class_set_props(dc, apple_gfx_pci_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo apple_gfx_pci_types[] = {
|
||||
{
|
||||
.name = TYPE_APPLE_GFX_PCI,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(AppleGFXPCIState),
|
||||
.class_init = apple_gfx_pci_class_init,
|
||||
.instance_init = apple_gfx_pci_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_PCIE_DEVICE },
|
||||
{ },
|
||||
},
|
||||
}
|
||||
};
|
||||
DEFINE_TYPES(apple_gfx_pci_types)
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Data structures and functions shared between variants of the macOS
|
||||
* ParavirtualizedGraphics.framework based apple-gfx display adapter.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef QEMU_APPLE_GFX_H
|
||||
#define QEMU_APPLE_GFX_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
#include "exec/memory.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "ui/surface.h"
|
||||
|
||||
#define TYPE_APPLE_GFX_MMIO "apple-gfx-mmio"
|
||||
#define TYPE_APPLE_GFX_PCI "apple-gfx-pci"
|
||||
|
||||
@class PGDeviceDescriptor;
|
||||
@protocol PGDevice;
|
||||
@protocol PGDisplay;
|
||||
@protocol MTLDevice;
|
||||
@protocol MTLTexture;
|
||||
@protocol MTLCommandQueue;
|
||||
|
||||
typedef QTAILQ_HEAD(, PGTask_s) PGTaskList;
|
||||
|
||||
typedef struct AppleGFXDisplayMode {
|
||||
uint16_t width_px;
|
||||
uint16_t height_px;
|
||||
uint16_t refresh_rate_hz;
|
||||
} AppleGFXDisplayMode;
|
||||
|
||||
typedef struct AppleGFXState {
|
||||
/* Initialised on init/realize() */
|
||||
MemoryRegion iomem_gfx;
|
||||
id<PGDevice> pgdev;
|
||||
id<PGDisplay> pgdisp;
|
||||
QemuConsole *con;
|
||||
id<MTLDevice> mtl;
|
||||
id<MTLCommandQueue> mtl_queue;
|
||||
AppleGFXDisplayMode *display_modes;
|
||||
uint32_t num_display_modes;
|
||||
|
||||
/* List `tasks` is protected by task_mutex */
|
||||
QemuMutex task_mutex;
|
||||
PGTaskList tasks;
|
||||
|
||||
/* Mutable state (BQL protected) */
|
||||
QEMUCursor *cursor;
|
||||
DisplaySurface *surface;
|
||||
id<MTLTexture> texture;
|
||||
int8_t pending_frames; /* # guest frames in the rendering pipeline */
|
||||
bool gfx_update_requested; /* QEMU display system wants a new frame */
|
||||
bool new_frame_ready; /* Guest has rendered a frame, ready to be used */
|
||||
bool using_managed_texture_storage;
|
||||
uint32_t rendering_frame_width;
|
||||
uint32_t rendering_frame_height;
|
||||
|
||||
/* Mutable state (atomic) */
|
||||
bool cursor_show;
|
||||
} AppleGFXState;
|
||||
|
||||
void apple_gfx_common_init(Object *obj, AppleGFXState *s, const char* obj_name);
|
||||
bool apple_gfx_common_realize(AppleGFXState *s, DeviceState *dev,
|
||||
PGDeviceDescriptor *desc, Error **errp);
|
||||
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_apple_gfx_display_mode;
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -61,6 +61,13 @@ 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])
|
||||
system_ss.add(when: 'CONFIG_MAC_PVG_PCI', if_true: [files('apple-gfx-pci.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()
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
#undef ALIGN
|
||||
#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
|
||||
|
||||
#define PIXEL_SIZE 0.2936875 //1280x1024 is 14.8" x 11.9"
|
||||
#define PIXEL_SIZE 0.2936875 /* 1280x1024 is 14.8" x 11.9" */
|
||||
|
||||
#define QXL_MODE(_x, _y, _b, _o) \
|
||||
{ .x_res = _x, \
|
||||
|
||||
@@ -194,3 +194,33 @@ 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_common_realize_modes_property(uint32_t num_modes) "using %u modes supplied by 'display-modes' device property"
|
||||
apple_gfx_display_mode(uint32_t mode_idx, uint16_t width_px, uint16_t height_px) "mode %2"PRIu32": %4"PRIu16"x%4"PRIu16
|
||||
|
||||
# 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"
|
||||
|
||||
|
||||
+2
-9
@@ -1652,17 +1652,10 @@ static void amdvi_sysbus_realize(DeviceState *dev, Error **errp)
|
||||
memory_region_add_subregion_overlap(&s->mr_sys, AMDVI_INT_ADDR_FIRST,
|
||||
&s->mr_ir, 1);
|
||||
|
||||
/* AMD IOMMU with x2APIC mode requires xtsup=on */
|
||||
if (x86ms->apic_id_limit > 255 && !s->xtsup) {
|
||||
error_report("AMD IOMMU with x2APIC confguration requires xtsup=on");
|
||||
if (kvm_enabled() && x86ms->apic_id_limit > 255 && !s->xtsup) {
|
||||
error_report("AMD IOMMU with x2APIC configuration requires xtsup=on");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (s->xtsup) {
|
||||
if (kvm_irqchip_is_split() && !kvm_enable_x2apic()) {
|
||||
error_report("AMD IOMMU xtsup=on requires support on the KVM side");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
pci_setup_iommu(bus, &amdvi_iommu_ops, s);
|
||||
amdvi_init(s);
|
||||
|
||||
+1
-1
@@ -214,7 +214,7 @@ static void kvm_apic_mem_write(void *opaque, hwaddr addr,
|
||||
static const MemoryRegionOps kvm_apic_io_ops = {
|
||||
.read = kvm_apic_mem_read,
|
||||
.write = kvm_apic_mem_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void kvm_apic_reset(APICCommonState *s)
|
||||
|
||||
+1
-1
@@ -139,7 +139,7 @@ static void create_gpex(MicrovmMachineState *mms)
|
||||
mms->gpex.mmio64.base, mmio64_alias);
|
||||
}
|
||||
|
||||
for (i = 0; i < GPEX_NUM_IRQS; i++) {
|
||||
for (i = 0; i < PCI_NUM_PINS; i++) {
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
|
||||
x86ms->gsi[mms->gpex.irq + i]);
|
||||
}
|
||||
|
||||
+2
-2
@@ -1068,7 +1068,7 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
|
||||
static const MemoryRegionOps ioport80_io_ops = {
|
||||
.write = ioport80_write,
|
||||
.read = ioport80_read,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.impl = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
@@ -1078,7 +1078,7 @@ static const MemoryRegionOps ioport80_io_ops = {
|
||||
static const MemoryRegionOps ioportF0_io_ops = {
|
||||
.write = ioportF0_write,
|
||||
.read = ioportF0_read,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.impl = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
|
||||
+1
-1
@@ -718,7 +718,7 @@ static uint64_t vapic_read(void *opaque, hwaddr addr, unsigned size)
|
||||
static const MemoryRegionOps vapic_ops = {
|
||||
.write = vapic_write,
|
||||
.read = vapic_read,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void vapic_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
@@ -36,7 +36,7 @@ static void xen_apic_mem_write(void *opaque, hwaddr addr,
|
||||
static const MemoryRegionOps xen_apic_io_ops = {
|
||||
.read = xen_apic_mem_read,
|
||||
.write = xen_apic_mem_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void xen_apic_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user