Skip to content
This repository was archived by the owner on Oct 27, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions compile_qemu_nyx.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ error()
echo "Available compile options: "
echo " - dynamic dynamically link libxdc and capstone4"
echo " - static statically link libxdc and capstone4"
echo " - full_static compile a full static QEMU build"
echo " - lto enable static linking and LTO (up to 10% better performance)"
echo " - debug enable debug and ASAN options"
echo " - debug_static enable debug, ASAN and static linking"
Expand All @@ -40,7 +41,7 @@ error()
compile_libraries()
{
case $1 in
"debug_static"|"static"|"lto")
"debug_static"|"static"|"full_static"|"lto")
echo "[!] Compiling capstone4..."
make -C $CAPSTONE_ROOT -j $(nproc)

Expand All @@ -55,7 +56,7 @@ configure_qemu()
QEMU_CONFIGURE="./configure --target-list=x86_64-softmmu --disable-docs --disable-gtk --disable-werror --disable-capstone --disable-libssh --disable-tools"

case $1 in
"debug_static"|"static"|"lto")
"debug_static"|"static"|"full_static"|"lto")
export LIBS="-L$CAPSTONE_ROOT -L$LIBXDC_ROOT/ $LIBS"
export QEMU_CFLAGS="-I$CAPSTONE_ROOT/include/ -I$LIBXDC_ROOT/ $QEMU_CFLAGS"
;;
Expand All @@ -76,6 +77,9 @@ configure_qemu()
"static")
$QEMU_CONFIGURE --enable-nyx --enable-nyx-static
;;
"full_static")
$QEMU_CONFIGURE --enable-nyx --enable-nyx-static --static --enable-slirp=git --disable-xkbcommon --disable-usb-redir --disable-smartcard --disable-opengl --audio-drv-list= --disable-libusb --disable-rdma --disable-libiscsi
;;
"lto")
$QEMU_CONFIGURE --enable-nyx --enable-nyx-static --enable-nyx-flto
;;
Expand All @@ -97,7 +101,7 @@ if [ "$#" -ne 1 ] ; then
fi

case $1 in
"dynamic"|"debug"|"debug_static"|"static"|"lto")
"dynamic"|"debug"|"debug_static"|"static"|"full_static"|"lto")
;;
*)
error
Expand Down
105 changes: 49 additions & 56 deletions hw/vfio/pci-quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@
#include "qapi/visitor.h"
#include <sys/ioctl.h>
#include "hw/hw.h"
#include "hw/i386/ich9.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/qdev-properties.h"
#include "pci.h"
#include "trace.h"
#include "hw/i386/e820_memory_layout.h"
#include "hw/i386/x86.h"
#include "hw/boards.h"

/* Use uin32_t for vendor & device so PCI_ANY_ID expands and cannot match hw */
static bool vfio_pci_is(VFIOPCIDevice *vdev, uint32_t vendor, uint32_t device)
Expand Down Expand Up @@ -1243,7 +1247,7 @@ static int igd_gen(VFIOPCIDevice *vdev)
typedef struct VFIOIGDQuirk {
struct VFIOPCIDevice *vdev;
uint32_t index;
uint32_t bdsm;
uint64_t bdsm;
} VFIOIGDQuirk;

#define IGD_GMCH 0x50 /* Graphics Control Register */
Expand Down Expand Up @@ -1416,19 +1420,18 @@ static int vfio_pci_igd_lpc_init(VFIOPCIDevice *vdev,
struct vfio_region_info *info)
{
PCIDevice *lpc_bridge;
int ret;
int ret = 0;

lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),
0, PCI_DEVFN(0x1f, 0));
if (!lpc_bridge) {
lpc_bridge = pci_create_simple(pci_device_root_bus(&vdev->pdev),
PCI_DEVFN(0x1f, 0), "vfio-pci-igd-lpc-bridge");
}

ret = vfio_pci_igd_copy(vdev, lpc_bridge, info, igd_lpc_bridge_infos,
ARRAY_SIZE(igd_lpc_bridge_infos));
if (!ret) {
trace_vfio_pci_igd_lpc_bridge_enabled(vdev->vbasedev.name);
ret = vfio_pci_igd_copy(vdev, lpc_bridge, info, igd_lpc_bridge_infos,
ARRAY_SIZE(igd_lpc_bridge_infos));
if (!ret) {
trace_vfio_pci_igd_lpc_bridge_enabled(vdev->vbasedev.name);
}
}

return ret;
Expand Down Expand Up @@ -1563,14 +1566,16 @@ static const MemoryRegionOps vfio_igd_index_quirk = {
static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
{
struct vfio_region_info *rom = NULL, *opregion = NULL,
*host = NULL, *lpc = NULL;
*host = NULL, *lpc = NULL, *dsm_info = NULL;
VFIOQuirk *quirk;
VFIOIGDQuirk *igd;
PCIDevice *lpc_bridge;
int i, ret, ggms_mb, gms_mb = 0, gen;
uint64_t *bdsm_size;
uint32_t gmch;
void *stolen;
int i, ret, gen;
uint64_t bdsm_size, bdsm;
uint32_t gmch, ggms_mb;
uint16_t cmd_orig, cmd;
X86MachineState *x86ms = X86_MACHINE(current_machine);
Error *err = NULL;

/*
Expand All @@ -1593,7 +1598,9 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),
0, PCI_DEVFN(0x1f, 0));
if (lpc_bridge && !object_dynamic_cast(OBJECT(lpc_bridge),
"vfio-pci-igd-lpc-bridge")) {
"vfio-pci-igd-lpc-bridge") &&
strcmp(object_class_get_name(object_get_class(OBJECT(lpc_bridge))),
TYPE_ICH9_LPC_DEVICE)) {
error_report("IGD device %s cannot support legacy mode due to existing "
"devices at address 1f.0", vdev->vbasedev.name);
return;
Expand Down Expand Up @@ -1666,6 +1673,15 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
goto out;
}

ret = vfio_get_dev_region_info(&vdev->vbasedev,
VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL,
VFIO_REGION_SUBTYPE_INTEL_IGD_DSM, &dsm_info);
if (ret) {
error_report("IGD device %s does not support data stolen memory access,"
"legacy mode disabled", vdev->vbasedev.name);
goto out;
}

gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, 4);

/*
Expand Down Expand Up @@ -1705,12 +1721,10 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
}

/* Setup our quirk to munge GTT addresses to the VM allocated buffer */
quirk = vfio_quirk_alloc(2);
quirk = vfio_quirk_alloc(3);
igd = quirk->data = g_malloc0(sizeof(*igd));
igd->vdev = vdev;
igd->index = ~0;
igd->bdsm = vfio_pci_read_config(&vdev->pdev, IGD_BDSM, 4);
igd->bdsm &= ~((1 * MiB) - 1); /* 1MB aligned */

memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_igd_index_quirk,
igd, "vfio-igd-index-quirk", 4);
Expand All @@ -1722,54 +1736,33 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
memory_region_add_subregion_overlap(vdev->bars[nr].region.mem,
4, &quirk->mem[1], 1);

QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);

/* Determine the size of stolen memory needed for GTT */
ggms_mb = (gmch >> (gen < 8 ? 8 : 6)) & 0x3;
if (gen > 6) {
ggms_mb = 1 << ggms_mb;
}

/*
* Assume we have no GMS memory, but allow it to be overrided by device
* option (experimental). The spec doesn't actually allow zero GMS when
* when IVD (IGD VGA Disable) is clear, but the claim is that it's unused,
* so let's not waste VM memory for it.
*/
gmch &= ~((gen < 8 ? 0x1f : 0xff) << (gen < 8 ? 3 : 8));
/* stolen memory includes GTT table and data stolen memory */
bdsm_size = dsm_info->size;

if (vdev->igd_gms) {
if (vdev->igd_gms <= 0x10) {
gms_mb = vdev->igd_gms * 32;
gmch |= vdev->igd_gms << (gen < 8 ? 3 : 8);
} else {
error_report("Unsupported IGD GMS value 0x%x", vdev->igd_gms);
vdev->igd_gms = 0;
}
if (pread(vdev->vbasedev.fd, &bdsm, sizeof(bdsm), dsm_info->offset) != sizeof(bdsm)) {
error_report("IGD device %s - failed to read BDSM address",
vdev->vbasedev.name);
}
igd->bdsm = bdsm & ~((1 * MiB) - 1); /* 1MB aligned */
stolen = mmap(NULL, bdsm_size, VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE,
MAP_SHARED, vdev->vbasedev.fd,
dsm_info->offset);
memory_region_init_ram_device_ptr(&quirk->mem[2], OBJECT(vdev),
"vfio-igd-stolen", bdsm_size, stolen);
memory_region_add_subregion_overlap(get_system_memory(),
igd->bdsm, &quirk->mem[2], 1);
e820_add_entry(igd->bdsm, bdsm_size, E820_RESERVED);
fw_cfg_modify_file(x86ms->fw_cfg, "etc/e820", e820_table, sizeof(struct e820_entry) * e820_get_num_entries());
fw_cfg_add_file(x86ms->fw_cfg, "etc/igd-dsm-base", g_memdup(&bdsm, sizeof(bdsm)), sizeof(bdsm));
fw_cfg_add_file(x86ms->fw_cfg, "etc/igd-dsm-size", g_memdup(&bdsm_size, sizeof(bdsm_size)), sizeof(bdsm_size));

/*
* Request reserved memory for stolen memory via fw_cfg. VM firmware
* must allocate a 1MB aligned reserved memory region below 4GB with
* the requested size (in bytes) for use by the Intel PCI class VGA
* device at VM address 00:02.0. The base address of this reserved
* memory region must be written to the device BDSM regsiter at PCI
* config offset 0x5C.
*/
bdsm_size = g_malloc(sizeof(*bdsm_size));
*bdsm_size = cpu_to_le64((ggms_mb + gms_mb) * MiB);
fw_cfg_add_file(fw_cfg_find(), "etc/igd-bdsm-size",
bdsm_size, sizeof(*bdsm_size));

/* GMCH is read-only, emulated */
pci_set_long(vdev->pdev.config + IGD_GMCH, gmch);
pci_set_long(vdev->pdev.wmask + IGD_GMCH, 0);
pci_set_long(vdev->emulated_config_bits + IGD_GMCH, ~0);

/* BDSM is read-write, emulated. The BIOS needs to be able to write it */
pci_set_long(vdev->pdev.config + IGD_BDSM, 0);
pci_set_long(vdev->pdev.wmask + IGD_BDSM, ~0);
pci_set_long(vdev->emulated_config_bits + IGD_BDSM, ~0);
QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);

/*
* This IOBAR gives us access to GTTADR, which allows us to write to
Expand Down Expand Up @@ -1802,7 +1795,7 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
vdev->vbasedev.name);
}

trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, ggms_mb + gms_mb);
trace_vfio_pci_igd_bdsm_enabled(vdev->vbasedev.name, bdsm_size >> 20);

out:
g_free(rom);
Expand Down
1 change: 1 addition & 0 deletions linux-headers/linux/vfio.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ struct vfio_region_info_cap_type {
#define VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION (1)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3)
#define VFIO_REGION_SUBTYPE_INTEL_IGD_DSM (4)

/* 10de vendor PCI sub-types */
/*
Expand Down