On Sun, 3 Oct 2021 23:53:10 +0800 Colin Xu <colin.xu@xxxxxxxxx> wrote: ... > static ssize_t vfio_pci_igd_rw(struct vfio_pci_core_device *vdev, > char __user *buf, size_t count, loff_t *ppos, > bool iswrite) > { > unsigned int i = VFIO_PCI_OFFSET_TO_INDEX(*ppos) - VFIO_PCI_NUM_REGIONS; > - void *base = vdev->region[i].data; > - loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK; > + struct igd_opregion_vbt *opregionvbt = vdev->region[i].data; > + loff_t pos = *ppos & VFIO_PCI_OFFSET_MASK, off = 0; > + size_t remaining; > > if (pos >= vdev->region[i].size || iswrite) > return -EINVAL; > > count = min(count, (size_t)(vdev->region[i].size - pos)); > + remaining = count; > + > + /* Copy until OpRegion version */ > + if (remaining && pos < OPREGION_VERSION) { > + size_t bytes = min(remaining, OPREGION_VERSION - (size_t)pos); mint_t(size_t,...) is probably the better option than casting the individual operands, especially when we're casting multiple operands as below. > + > + if (igd_opregion_shift_copy(buf, &off, > + opregionvbt->opregion + pos, &pos, > + &remaining, bytes)) > + return -EFAULT; > + } > ... > /* > - * Support opregion v2.1+ > - * When VBT data exceeds 6KB size and cannot be within mailbox #4, then > - * the Extended VBT region next to opregion is used to hold the VBT data. > - * RVDA (Relative Address of VBT Data from Opregion Base) and RVDS > - * (Raw VBT Data Size) from opregion structure member are used to hold the > - * address from region base and size of VBT data. RVDA/RVDS are not > - * defined before opregion 2.0. > + * OpRegion and VBT: > + * When VBT data doesn't exceed 6KB, it's stored in Mailbox #4. > + * When VBT data exceeds 6KB size, Mailbox #4 is no longer large enough > + * to hold the VBT data, the Extended VBT region is introduced since > + * OpRegion 2.0 to hold the VBT data. Since OpRegion 2.0, RVDA/RVDS are > + * introduced to define the extended VBT data location and size. > + * OpRegion 2.0: RVDA defines the absolute physical address of the > + * extended VBT data, RVDS defines the VBT data size. > + * OpRegion 2.1 and above: RVDA defines the relative address of the > + * extended VBT data to OpRegion base, RVDS defines the VBT data size. > * > - * opregion 2.1+: RVDA is unsigned, relative offset from > - * opregion base, and should point to the end of opregion. > - * otherwise, exposing to userspace to allow read access to everything between > - * the OpRegion and VBT is not safe. > - * RVDS is defined as size in bytes. > - * > - * opregion 2.0: rvda is the physical VBT address. > - * Since rvda is HPA it cannot be directly used in guest. > - * And it should not be practically available for end user,so it is not supported. > + * Due to the RVDA difference in OpRegion VBT (also the only diff between > + * 2.0 and 2.1), expose OpRegion and VBT as a contiguous range for > + * OpRegion 2.0 and above makes it possible to support the non-contiguous The lines ending between$ and contiguous$ are still just over 80 columns. Thanks, Alex