mirror of https://github.com/xemu-project/xemu.git
vfio queue:
* Support for IGDs of gen 11 and later * Coverity fixes -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmbpWl0ACgkQUaNDx8/7 7KFYJhAAu8Dyf96RUr4ucu/VaSlTi/rk/i5sivD4EXiCOf2qpQtyoo+C8DJmjAZg nC+4IpD2vu2C/xaZoQ4o6uQL7c45dOup59jcbKO+6NekF521Y6aq9OvE5v55CAwu R38UWI6ZX5qqyU/tA39/s7migIvCtK7VgTzEs2Lpzw8WetCFattvrEiKHt09fNdX kSPdFVV6FymOowAekQtI2JACr8C5nm8x9npzyL1SjauvWA70aOU9h1iHoIxHGKFF jlotd6v16c0Z260AUP/RDBwf8wqg2MtwBOI3qVGYD20Xd7tRQkLlFp8X5lNw4pHr eylqqxW3E4LJ4vSWpi4Jj2tZN5tZl8X927ew79D2gf69R8f1l+5CG/qqynMRbZ0b gE1E5UNfEkXYX9PMuf2uenoiahMxh7ZHwzJmtFcTLGyHGudSaUu3S7Yu5a1R0ZDf 8OyzE1E1X/8uCABvSgPphtSfYD9kXKiwNJSPrj3PZ1nXgNoA6BDi5sOeTPm0POBA IfB10VEXDd61KPFKGQqZ1Qqrvb0LsCTvFTwCHRHBEB/F/ykwTX9dzrTInkTBTiQU OyDjKZvR2ACjysuFxvpA2fhhF7KCmCwg7M/YsKyVLKq2r3TdBnDS1DHm7Z5ebNu4 vgV4fsPCnjaQxOHEHZmh+rxG0E2dOGMiCieY9ooJ6jeomKQ+d60= =cIWS -----END PGP SIGNATURE----- Merge tag 'pull-vfio-20240917' of https://github.com/legoater/qemu into staging vfio queue: * Support for IGDs of gen 11 and later * Coverity fixes # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmbpWl0ACgkQUaNDx8/7 # 7KFYJhAAu8Dyf96RUr4ucu/VaSlTi/rk/i5sivD4EXiCOf2qpQtyoo+C8DJmjAZg # nC+4IpD2vu2C/xaZoQ4o6uQL7c45dOup59jcbKO+6NekF521Y6aq9OvE5v55CAwu # R38UWI6ZX5qqyU/tA39/s7migIvCtK7VgTzEs2Lpzw8WetCFattvrEiKHt09fNdX # kSPdFVV6FymOowAekQtI2JACr8C5nm8x9npzyL1SjauvWA70aOU9h1iHoIxHGKFF # jlotd6v16c0Z260AUP/RDBwf8wqg2MtwBOI3qVGYD20Xd7tRQkLlFp8X5lNw4pHr # eylqqxW3E4LJ4vSWpi4Jj2tZN5tZl8X927ew79D2gf69R8f1l+5CG/qqynMRbZ0b # gE1E5UNfEkXYX9PMuf2uenoiahMxh7ZHwzJmtFcTLGyHGudSaUu3S7Yu5a1R0ZDf # 8OyzE1E1X/8uCABvSgPphtSfYD9kXKiwNJSPrj3PZ1nXgNoA6BDi5sOeTPm0POBA # IfB10VEXDd61KPFKGQqZ1Qqrvb0LsCTvFTwCHRHBEB/F/ykwTX9dzrTInkTBTiQU # OyDjKZvR2ACjysuFxvpA2fhhF7KCmCwg7M/YsKyVLKq2r3TdBnDS1DHm7Z5ebNu4 # vgV4fsPCnjaQxOHEHZmh+rxG0E2dOGMiCieY9ooJ6jeomKQ+d60= # =cIWS # -----END PGP SIGNATURE----- # gpg: Signature made Tue 17 Sep 2024 11:30:53 BST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-vfio-20240917' of https://github.com/legoater/qemu: vfio/igd: correctly calculate stolen memory size for gen 9 and later vfio/igd: don't set stolen memory size to zero vfio/igd: add ID's for ElkhartLake and TigerLake vfio/igd: add new bar0 quirk to emulate BDSM mirror vfio/igd: use new BDSM register location and size for gen 11 and later vfio/igd: support legacy mode for all known generations vfio/igd: return an invalid generation for unknown devices hw/vfio/pci.c: Use correct type in trace_vfio_msix_early_setup() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
da7de6ef57
185
hw/vfio/igd.c
185
hw/vfio/igd.c
|
@ -88,19 +88,30 @@ static int igd_gen(VFIOPCIDevice *vdev)
|
|||
case 0x2200:
|
||||
case 0x5900:
|
||||
return 8;
|
||||
/* ElkhartLake */
|
||||
case 0x4500:
|
||||
return 11;
|
||||
/* TigerLake */
|
||||
case 0x9A00:
|
||||
return 12;
|
||||
}
|
||||
|
||||
return 8; /* Assume newer is compatible */
|
||||
/*
|
||||
* Unfortunately, Intel changes it's specification quite often. This makes
|
||||
* it impossible to use a suitable default value for unknown devices.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
typedef struct VFIOIGDQuirk {
|
||||
struct VFIOPCIDevice *vdev;
|
||||
uint32_t index;
|
||||
uint32_t bdsm;
|
||||
uint64_t bdsm;
|
||||
} VFIOIGDQuirk;
|
||||
|
||||
#define IGD_GMCH 0x50 /* Graphics Control Register */
|
||||
#define IGD_BDSM 0x5c /* Base Data of Stolen Memory */
|
||||
#define IGD_BDSM_GEN11 0xc0 /* Base Data of Stolen Memory of gen 11 and later */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -309,9 +320,13 @@ static void vfio_igd_quirk_data_write(void *opaque, hwaddr addr,
|
|||
*/
|
||||
if ((igd->index % 4 == 1) && igd->index < vfio_igd_gtt_max(vdev)) {
|
||||
if (gen < 8 || (igd->index % 8 == 1)) {
|
||||
uint32_t base;
|
||||
uint64_t base;
|
||||
|
||||
base = pci_get_long(vdev->pdev.config + IGD_BDSM);
|
||||
if (gen < 11) {
|
||||
base = pci_get_long(vdev->pdev.config + IGD_BDSM);
|
||||
} else {
|
||||
base = pci_get_quad(vdev->pdev.config + IGD_BDSM_GEN11);
|
||||
}
|
||||
if (!base) {
|
||||
hw_error("vfio-igd: Guest attempted to program IGD GTT before "
|
||||
"BIOS reserved stolen memory. Unsupported BIOS?");
|
||||
|
@ -365,6 +380,128 @@ static const MemoryRegionOps vfio_igd_index_quirk = {
|
|||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
#define IGD_BDSM_MMIO_OFFSET 0x1080C0
|
||||
|
||||
static uint64_t vfio_igd_quirk_bdsm_read(void *opaque,
|
||||
hwaddr addr, unsigned size)
|
||||
{
|
||||
VFIOPCIDevice *vdev = opaque;
|
||||
uint64_t offset;
|
||||
|
||||
offset = IGD_BDSM_GEN11 + addr;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
return pci_get_byte(vdev->pdev.config + offset);
|
||||
case 2:
|
||||
return pci_get_word(vdev->pdev.config + offset);
|
||||
case 4:
|
||||
return pci_get_long(vdev->pdev.config + offset);
|
||||
case 8:
|
||||
return pci_get_quad(vdev->pdev.config + offset);
|
||||
default:
|
||||
hw_error("igd: unsupported read size, %u bytes", size);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vfio_igd_quirk_bdsm_write(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
VFIOPCIDevice *vdev = opaque;
|
||||
uint64_t offset;
|
||||
|
||||
offset = IGD_BDSM_GEN11 + addr;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
pci_set_byte(vdev->pdev.config + offset, data);
|
||||
break;
|
||||
case 2:
|
||||
pci_set_word(vdev->pdev.config + offset, data);
|
||||
break;
|
||||
case 4:
|
||||
pci_set_long(vdev->pdev.config + offset, data);
|
||||
break;
|
||||
case 8:
|
||||
pci_set_quad(vdev->pdev.config + offset, data);
|
||||
break;
|
||||
default:
|
||||
hw_error("igd: unsupported read size, %u bytes", size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps vfio_igd_bdsm_quirk = {
|
||||
.read = vfio_igd_quirk_bdsm_read,
|
||||
.write = vfio_igd_quirk_bdsm_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
{
|
||||
VFIOQuirk *quirk;
|
||||
int gen;
|
||||
|
||||
/*
|
||||
* This must be an Intel VGA device at address 00:02.0 for us to even
|
||||
* consider enabling legacy mode. Some driver have dependencies on the PCI
|
||||
* bus address.
|
||||
*/
|
||||
if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||
|
||||
!vfio_is_vga(vdev) || nr != 0 ||
|
||||
&vdev->pdev != pci_find_device(pci_device_root_bus(&vdev->pdev),
|
||||
0, PCI_DEVFN(0x2, 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only on IGD devices of gen 11 and above, the BDSM register is mirrored
|
||||
* into MMIO space and read from MMIO space by the Windows driver.
|
||||
*/
|
||||
gen = igd_gen(vdev);
|
||||
if (gen < 11) {
|
||||
return;
|
||||
}
|
||||
|
||||
quirk = vfio_quirk_alloc(1);
|
||||
quirk->data = vdev;
|
||||
|
||||
memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_igd_bdsm_quirk,
|
||||
vdev, "vfio-igd-bdsm-quirk", 8);
|
||||
memory_region_add_subregion_overlap(vdev->bars[0].region.mem,
|
||||
IGD_BDSM_MMIO_OFFSET, &quirk->mem[0],
|
||||
1);
|
||||
|
||||
QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
|
||||
}
|
||||
|
||||
static int igd_get_stolen_mb(int gen, uint32_t gmch)
|
||||
{
|
||||
int gms;
|
||||
|
||||
if (gen < 8) {
|
||||
gms = (gmch >> 3) & 0x1f;
|
||||
} else {
|
||||
gms = (gmch >> 8) & 0xff;
|
||||
}
|
||||
|
||||
if (gen < 9) {
|
||||
if (gms > 0x10) {
|
||||
error_report("Unsupported IGD GMS value 0x%x", gms);
|
||||
return 0;
|
||||
}
|
||||
return gms * 32;
|
||||
} else {
|
||||
if (gms < 0xf0)
|
||||
return gms * 32;
|
||||
else
|
||||
return gms * 4 + 4;
|
||||
}
|
||||
}
|
||||
|
||||
void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
||||
{
|
||||
g_autofree struct vfio_region_info *rom = NULL;
|
||||
|
@ -412,7 +549,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
|||
* devices maintain compatibility with generation 8.
|
||||
*/
|
||||
gen = igd_gen(vdev);
|
||||
if (gen != 6 && gen != 8) {
|
||||
if (gen == -1) {
|
||||
error_report("IGD device %s is unsupported in legacy mode, "
|
||||
"try SandyBridge or newer", vdev->vbasedev.name);
|
||||
return;
|
||||
|
@ -515,7 +652,13 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
|||
igd = quirk->data = g_malloc0(sizeof(*igd));
|
||||
igd->vdev = vdev;
|
||||
igd->index = ~0;
|
||||
igd->bdsm = vfio_pci_read_config(&vdev->pdev, IGD_BDSM, 4);
|
||||
if (gen < 11) {
|
||||
igd->bdsm = vfio_pci_read_config(&vdev->pdev, IGD_BDSM, 4);
|
||||
} else {
|
||||
igd->bdsm = vfio_pci_read_config(&vdev->pdev, IGD_BDSM_GEN11, 4);
|
||||
igd->bdsm |=
|
||||
(uint64_t)vfio_pci_read_config(&vdev->pdev, IGD_BDSM_GEN11 + 4, 4) << 32;
|
||||
}
|
||||
igd->bdsm &= ~((1 * MiB) - 1); /* 1MB aligned */
|
||||
|
||||
memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_igd_index_quirk,
|
||||
|
@ -536,23 +679,7 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
|||
ggms_mb = 1 << ggms_mb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume we have no GMS memory, but allow it to be overridden 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));
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
gms_mb = igd_get_stolen_mb(gen, gmch);
|
||||
|
||||
/*
|
||||
* Request reserved memory for stolen memory via fw_cfg. VM firmware
|
||||
|
@ -573,9 +700,15 @@ void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr)
|
|||
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);
|
||||
if (gen < 11) {
|
||||
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);
|
||||
} else {
|
||||
pci_set_quad(vdev->pdev.config + IGD_BDSM_GEN11, 0);
|
||||
pci_set_quad(vdev->pdev.wmask + IGD_BDSM_GEN11, ~0);
|
||||
pci_set_quad(vdev->emulated_config_bits + IGD_BDSM_GEN11, ~0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This IOBAR gives us access to GTTADR, which allows us to write to
|
||||
|
|
|
@ -1259,6 +1259,7 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr)
|
|||
vfio_probe_nvidia_bar0_quirk(vdev, nr);
|
||||
vfio_probe_rtl8168_bar2_quirk(vdev, nr);
|
||||
#ifdef CONFIG_VFIO_IGD
|
||||
vfio_probe_igd_bar0_quirk(vdev, nr);
|
||||
vfio_probe_igd_bar4_quirk(vdev, nr);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -215,6 +215,7 @@ void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev);
|
|||
bool vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp);
|
||||
void vfio_quirk_reset(VFIOPCIDevice *vdev);
|
||||
VFIOQuirk *vfio_quirk_alloc(int nr_mem);
|
||||
void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr);
|
||||
void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr);
|
||||
|
||||
extern const PropertyInfo qdev_prop_nv_gpudirect_clique;
|
||||
|
|
|
@ -27,7 +27,7 @@ vfio_vga_read(uint64_t addr, int size, uint64_t data) " (0x%"PRIx64", %d) = 0x%"
|
|||
vfio_pci_read_config(const char *name, int addr, int len, int val) " (%s, @0x%x, len=0x%x) 0x%x"
|
||||
vfio_pci_write_config(const char *name, int addr, int val, int len) " (%s, @0x%x, 0x%x, len=0x%x)"
|
||||
vfio_msi_setup(const char *name, int pos) "%s PCI MSI CAP @0x%x"
|
||||
vfio_msix_early_setup(const char *name, int pos, int table_bar, int offset, int entries, bool noresize) "%s PCI MSI-X CAP @0x%x, BAR %d, offset 0x%x, entries %d, noresize %d"
|
||||
vfio_msix_early_setup(const char *name, int pos, int table_bar, uint64_t offset, int entries, bool noresize) "%s PCI MSI-X CAP @0x%x, BAR %d, offset 0x%"PRIx64", entries %d, noresize %d"
|
||||
vfio_check_pcie_flr(const char *name) "%s Supports FLR via PCIe cap"
|
||||
vfio_check_pm_reset(const char *name) "%s Supports PM reset"
|
||||
vfio_check_af_flr(const char *name) "%s Supports FLR via AF cap"
|
||||
|
|
Loading…
Reference in New Issue