[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 6/8] vfio/igd: emulate GGC register in mmio bar0
From: |
Tomita Moeko |
Subject: |
Re: [PATCH 6/8] vfio/igd: emulate GGC register in mmio bar0 |
Date: |
Tue, 3 Dec 2024 01:44:45 +0800 |
User-agent: |
Mozilla Thunderbird |
On 12/2/24 17:39, Corvin Köhne wrote:
> On Mon, 2024-12-02 at 00:09 +0800, Tomita Moeko wrote:
>> CAUTION: External Email!!
>> The GGC register at 0x50 of pci config space is a mirror of the same
>> register at 0x108040 of mmio bar0 [1]. i915 driver also reads that
>> register from mmio bar0 instead of config space. As GGC is programmed
>> and emulated by qemu, the mmio address should also be emulated, in the
>> same way of BDSM register.
>>
>> A macro is defined to simplify the declaration of MemoryRegionOps for
>> a register mirrored to pcie config space.
>>
>> [1] 4.1.28, 12th Generation Intel Core Processors Datasheet Volume 2
>> https://www.intel.com/content/www/us/en/content-details/655259
>>
>> Signed-off-by: Tomita Moeko <tomitamoeko@gmail.com>
>> ---
>> hw/vfio/igd.c | 67 ++++++++++++++++++++++++++++++++-------------------
>> 1 file changed, 42 insertions(+), 25 deletions(-)
>>
>> diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
>> index a86faf2fa9..07700dce30 100644
>> --- a/hw/vfio/igd.c
>> +++ b/hw/vfio/igd.c
>> @@ -415,16 +415,9 @@ 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)
>> +static uint64_t vfio_igd_pci_config_read(VFIOPCIDevice *vdev, uint64_t
>> offset,
>> + 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);
>> @@ -442,14 +435,12 @@ static uint64_t vfio_igd_quirk_bdsm_read(void *opaque,
>> 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;
>> +#define IGD_GGC_MMIO_OFFSET 0x108040
>> +#define IGD_BDSM_MMIO_OFFSET 0x1080C0
>>
>
> While already moving this down, I would move it even more down in front of
> vfio_probe_igd_bar0_quirk
> to the place where it's actually used.
Will move it right above vfio_probe_igd_bar0_quirk()
>> +static void vfio_igd_pci_config_write(VFIOPCIDevice *vdev, uint64_t offset,
>> + uint64_t data, unsigned size)
>> +{
>> switch (size) {
>> case 1:
>> pci_set_byte(vdev->pdev.config + offset, data);
>> @@ -464,17 +455,35 @@ static void vfio_igd_quirk_bdsm_write(void *opaque,
>> hwaddr addr,
>> pci_set_quad(vdev->pdev.config + offset, data);
>> break;
>> default:
>> - hw_error("igd: unsupported read size, %u bytes", size);
>> + hw_error("igd: unsupported write size, %u bytes", size);
>
> It would make sense to log the faulting address too.
Good catch
>> break;
>> }
>> }
>>
>> -static const MemoryRegionOps vfio_igd_bdsm_quirk = {
>> - .read = vfio_igd_quirk_bdsm_read,
>> - .write = vfio_igd_quirk_bdsm_write,
>> - .endianness = DEVICE_LITTLE_ENDIAN,
>> +#define VFIO_IGD_QUIRK_MIRROR_REG(reg, name) \
>> +static uint64_t vfio_igd_quirk_read_##name(void *opaque, \
>> + hwaddr addr, unsigned size) \
>> +{ \
>> + VFIOPCIDevice *vdev = opaque; \
>> + return vfio_igd_pci_config_read(vdev, reg + addr, size); \
>> +} \
>> + \
>> +static void vfio_igd_quirk_write_##name(void *opaque, hwaddr addr, \
>> + uint64_t data, unsigned size) \
>> +{ \
>> + VFIOPCIDevice *vdev = opaque; \
>> + vfio_igd_pci_config_write(vdev, reg + addr, data, size); \
>> +} \
>> + \
>> +static const MemoryRegionOps vfio_igd_quirk_mirror_##name = { \
>> + .read = vfio_igd_quirk_read_##name, \
>> + .write = vfio_igd_quirk_write_##name, \
>> + .endianness = DEVICE_LITTLE_ENDIAN, \
>> };
>>
>> +VFIO_IGD_QUIRK_MIRROR_REG(IGD_GMCH, ggc)
>> +VFIO_IGD_QUIRK_MIRROR_REG(IGD_BDSM_GEN11, bdsm)
>> +
>> void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr)
>> {
>> VFIOQuirk *quirk;
>> @@ -501,13 +510,21 @@ void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev,
>> int nr)
>> return;
>> }
>>
>> - quirk = vfio_quirk_alloc(1);
>> + quirk = vfio_quirk_alloc(2);
>> quirk->data = vdev;
>>
>> - memory_region_init_io(&quirk->mem[0], OBJECT(vdev),
>> &vfio_igd_bdsm_quirk,
>> - vdev, "vfio-igd-bdsm-quirk", 8);
>> + memory_region_init_io(&quirk->mem[0], OBJECT(vdev),
>> + &vfio_igd_quirk_mirror_ggc, vdev,
>> + "vfio-igd-ggc-quirk", 2);
>> + memory_region_add_subregion_overlap(vdev->bars[0].region.mem,
>> + IGD_GGC_MMIO_OFFSET, &quirk->mem[0],
>> + 1);
>> +
>> + memory_region_init_io(&quirk->mem[1], OBJECT(vdev),
>> + &vfio_igd_quirk_mirror_bdsm, vdev,
>> + "vfio-igd-bdsm-quirk", 8);
>> memory_region_add_subregion_overlap(vdev->bars[0].region.mem,
>> - IGD_BDSM_MMIO_OFFSET,
>> &quirk->mem[0],
>> + IGD_BDSM_MMIO_OFFSET,
>> &quirk->mem[1],
>> 1);
>>
>> QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
>
> I slightly prefer splitting this patch into two. The first one adding a new
> macro for mirroring
> register and the second one adding the GGC mirror. However, that's just my
> personal preference.
>
Will split them in v2.
- [PATCH 0/8] vfio/igd: Enable legacy mode on more devices, Tomita Moeko, 2024/12/01
- [PATCH 7/8] vfio/igd: emulate BDSM in mmio bar0 for gen 6-10 devices, Tomita Moeko, 2024/12/01
- [PATCH 8/8] vfio/igd: add x-igd-gms option back to set DSM region size for guest, Tomita Moeko, 2024/12/01
- [PATCH 6/8] vfio/igd: emulate GGC register in mmio bar0, Tomita Moeko, 2024/12/01
- [PATCH 3/8] vfio/igd: remove unsupported device ids, Tomita Moeko, 2024/12/01
- [PATCH 4/8] vfio/igd: align generation with i915 kernel driver, Tomita Moeko, 2024/12/01
- [PATCH 2/8] vfio/igd: canonicalize memory size calculations, Tomita Moeko, 2024/12/01