vfio/igd: add macro for declaring mirrored registers

igd devices have multipe registers mirroring mmio address and pci
config space, more than a single BDSM register. To support this,
the read/write functions are made common and a macro is defined to
simplify the declaration of MemoryRegionOps.

Signed-off-by: Tomita Moeko <tomitamoeko@gmail.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
Link: https://lore.kernel.org/r/20241206122749.9893-8-tomitamoeko@gmail.com
[ clg : Fixed conversion specifier on 32-bit platform ]
Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
Tomita Moeko 2024-12-06 20:27:45 +08:00 committed by Cédric Le Goater
parent 960f62770a
commit 1a2623b5c9

View file

@ -421,16 +421,9 @@ static const MemoryRegionOps vfio_igd_index_quirk = {
.endianness = DEVICE_LITTLE_ENDIAN, .endianness = DEVICE_LITTLE_ENDIAN,
}; };
#define IGD_BDSM_MMIO_OFFSET 0x1080C0 static uint64_t vfio_igd_pci_config_read(VFIOPCIDevice *vdev, uint64_t offset,
unsigned size)
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) { switch (size) {
case 1: case 1:
return pci_get_byte(vdev->pdev.config + offset); return pci_get_byte(vdev->pdev.config + offset);
@ -441,21 +434,17 @@ static uint64_t vfio_igd_quirk_bdsm_read(void *opaque,
case 8: case 8:
return pci_get_quad(vdev->pdev.config + offset); return pci_get_quad(vdev->pdev.config + offset);
default: default:
hw_error("igd: unsupported read size, %u bytes", size); hw_error("igd: unsupported pci config read at %"PRIx64", size %u",
offset, size);
break; break;
} }
return 0; return 0;
} }
static void vfio_igd_quirk_bdsm_write(void *opaque, hwaddr addr, static void vfio_igd_pci_config_write(VFIOPCIDevice *vdev, uint64_t offset,
uint64_t data, unsigned size) uint64_t data, unsigned size)
{ {
VFIOPCIDevice *vdev = opaque;
uint64_t offset;
offset = IGD_BDSM_GEN11 + addr;
switch (size) { switch (size) {
case 1: case 1:
pci_set_byte(vdev->pdev.config + offset, data); pci_set_byte(vdev->pdev.config + offset, data);
@ -470,17 +459,39 @@ static void vfio_igd_quirk_bdsm_write(void *opaque, hwaddr addr,
pci_set_quad(vdev->pdev.config + offset, data); pci_set_quad(vdev->pdev.config + offset, data);
break; break;
default: default:
hw_error("igd: unsupported read size, %u bytes", size); hw_error("igd: unsupported pci config write at %"PRIx64", size %u",
offset, size);
break; break;
} }
} }
static const MemoryRegionOps vfio_igd_bdsm_quirk = { #define VFIO_IGD_QUIRK_MIRROR_REG(reg, name) \
.read = vfio_igd_quirk_bdsm_read, static uint64_t vfio_igd_quirk_read_##name(void *opaque, \
.write = vfio_igd_quirk_bdsm_write, hwaddr addr, unsigned size) \
.endianness = DEVICE_LITTLE_ENDIAN, { \
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_BDSM_GEN11, bdsm)
#define IGD_BDSM_MMIO_OFFSET 0x1080C0
void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr) void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr)
{ {
VFIOQuirk *quirk; VFIOQuirk *quirk;
@ -510,8 +521,9 @@ void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr)
quirk = vfio_quirk_alloc(1); quirk = vfio_quirk_alloc(1);
quirk->data = vdev; quirk->data = vdev;
memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_igd_bdsm_quirk, memory_region_init_io(&quirk->mem[0], OBJECT(vdev),
vdev, "vfio-igd-bdsm-quirk", 8); &vfio_igd_quirk_mirror_bdsm, vdev,
"vfio-igd-bdsm-quirk", 8);
memory_region_add_subregion_overlap(vdev->bars[0].region.mem, memory_region_add_subregion_overlap(vdev->bars[0].region.mem,
IGD_BDSM_MMIO_OFFSET, &quirk->mem[0], IGD_BDSM_MMIO_OFFSET, &quirk->mem[0],
1); 1);