Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vfio/pci: rename and export range_intersect_range

range_intersect_range determines an overlap between two ranges. If an
overlap, the helper function returns the overlapping offset and size.

The VFIO PCI variant driver emulates the PCI config space BAR offset
registers. These offset may be accessed for read/write with a variety
of lengths including sub-word sizes from sub-word offsets. The driver
makes use of this helper function to read/write the targeted part of
the emulated register.

Make this a vfio_pci_core function, rename and export as GPL. Also
update references in virtio driver.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Yishai Hadas <yishaih@nvidia.com>
Signed-off-by: Ankit Agrawal <ankita@nvidia.com>
Link: https://lore.kernel.org/r/20240220115055.23546-3-ankita@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

authored by

Ankit Agrawal and committed by
Alex Williamson
30e920e1 4de676d4

+73 -46
+42
drivers/vfio/pci/vfio_pci_config.c
··· 1966 1966 1967 1967 return done; 1968 1968 } 1969 + 1970 + /** 1971 + * vfio_pci_core_range_intersect_range() - Determine overlap between a buffer 1972 + * and register offset ranges. 1973 + * @buf_start: start offset of the buffer 1974 + * @buf_cnt: number of buffer bytes 1975 + * @reg_start: start register offset 1976 + * @reg_cnt: number of register bytes 1977 + * @buf_offset: start offset of overlap in the buffer 1978 + * @intersect_count: number of overlapping bytes 1979 + * @register_offset: start offset of overlap in register 1980 + * 1981 + * Returns: true if there is overlap, false if not. 1982 + * The overlap start and size is returned through function args. 1983 + */ 1984 + bool vfio_pci_core_range_intersect_range(loff_t buf_start, size_t buf_cnt, 1985 + loff_t reg_start, size_t reg_cnt, 1986 + loff_t *buf_offset, 1987 + size_t *intersect_count, 1988 + size_t *register_offset) 1989 + { 1990 + if (buf_start <= reg_start && 1991 + buf_start + buf_cnt > reg_start) { 1992 + *buf_offset = reg_start - buf_start; 1993 + *intersect_count = min_t(size_t, reg_cnt, 1994 + buf_start + buf_cnt - reg_start); 1995 + *register_offset = 0; 1996 + return true; 1997 + } 1998 + 1999 + if (buf_start > reg_start && 2000 + buf_start < reg_start + reg_cnt) { 2001 + *buf_offset = 0; 2002 + *intersect_count = min_t(size_t, buf_cnt, 2003 + reg_start + reg_cnt - buf_start); 2004 + *register_offset = buf_start - reg_start; 2005 + return true; 2006 + } 2007 + 2008 + return false; 2009 + } 2010 + EXPORT_SYMBOL_GPL(vfio_pci_core_range_intersect_range);
+26 -46
drivers/vfio/pci/virtio/main.c
··· 132 132 return ret ? ret : count; 133 133 } 134 134 135 - static bool range_intersect_range(loff_t range1_start, size_t count1, 136 - loff_t range2_start, size_t count2, 137 - loff_t *start_offset, 138 - size_t *intersect_count, 139 - size_t *register_offset) 140 - { 141 - if (range1_start <= range2_start && 142 - range1_start + count1 > range2_start) { 143 - *start_offset = range2_start - range1_start; 144 - *intersect_count = min_t(size_t, count2, 145 - range1_start + count1 - range2_start); 146 - *register_offset = 0; 147 - return true; 148 - } 149 - 150 - if (range1_start > range2_start && 151 - range1_start < range2_start + count2) { 152 - *start_offset = 0; 153 - *intersect_count = min_t(size_t, count1, 154 - range2_start + count2 - range1_start); 155 - *register_offset = range1_start - range2_start; 156 - return true; 157 - } 158 - 159 - return false; 160 - } 161 - 162 135 static ssize_t virtiovf_pci_read_config(struct vfio_device *core_vdev, 163 136 char __user *buf, size_t count, 164 137 loff_t *ppos) ··· 151 178 if (ret < 0) 152 179 return ret; 153 180 154 - if (range_intersect_range(pos, count, PCI_DEVICE_ID, sizeof(val16), 155 - &copy_offset, &copy_count, &register_offset)) { 181 + if (vfio_pci_core_range_intersect_range(pos, count, PCI_DEVICE_ID, 182 + sizeof(val16), &copy_offset, 183 + &copy_count, &register_offset)) { 156 184 val16 = cpu_to_le16(VIRTIO_TRANS_ID_NET); 157 185 if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset, copy_count)) 158 186 return -EFAULT; 159 187 } 160 188 161 189 if ((le16_to_cpu(virtvdev->pci_cmd) & PCI_COMMAND_IO) && 162 - range_intersect_range(pos, count, PCI_COMMAND, sizeof(val16), 163 - &copy_offset, &copy_count, &register_offset)) { 190 + vfio_pci_core_range_intersect_range(pos, count, PCI_COMMAND, 191 + sizeof(val16), &copy_offset, 192 + &copy_count, &register_offset)) { 164 193 if (copy_from_user((void *)&val16 + register_offset, buf + copy_offset, 165 194 copy_count)) 166 195 return -EFAULT; ··· 172 197 return -EFAULT; 173 198 } 174 199 175 - if (range_intersect_range(pos, count, PCI_REVISION_ID, sizeof(val8), 176 - &copy_offset, &copy_count, &register_offset)) { 200 + if (vfio_pci_core_range_intersect_range(pos, count, PCI_REVISION_ID, 201 + sizeof(val8), &copy_offset, 202 + &copy_count, &register_offset)) { 177 203 /* Transional needs to have revision 0 */ 178 204 val8 = 0; 179 205 if (copy_to_user(buf + copy_offset, &val8, copy_count)) 180 206 return -EFAULT; 181 207 } 182 208 183 - if (range_intersect_range(pos, count, PCI_BASE_ADDRESS_0, sizeof(val32), 184 - &copy_offset, &copy_count, &register_offset)) { 209 + if (vfio_pci_core_range_intersect_range(pos, count, PCI_BASE_ADDRESS_0, 210 + sizeof(val32), &copy_offset, 211 + &copy_count, &register_offset)) { 185 212 u32 bar_mask = ~(virtvdev->bar0_virtual_buf_size - 1); 186 213 u32 pci_base_addr_0 = le32_to_cpu(virtvdev->pci_base_addr_0); 187 214 ··· 192 215 return -EFAULT; 193 216 } 194 217 195 - if (range_intersect_range(pos, count, PCI_SUBSYSTEM_ID, sizeof(val16), 196 - &copy_offset, &copy_count, &register_offset)) { 218 + if (vfio_pci_core_range_intersect_range(pos, count, PCI_SUBSYSTEM_ID, 219 + sizeof(val16), &copy_offset, 220 + &copy_count, &register_offset)) { 197 221 /* 198 222 * Transitional devices use the PCI subsystem device id as 199 223 * virtio device id, same as legacy driver always did. ··· 205 227 return -EFAULT; 206 228 } 207 229 208 - if (range_intersect_range(pos, count, PCI_SUBSYSTEM_VENDOR_ID, sizeof(val16), 209 - &copy_offset, &copy_count, &register_offset)) { 230 + if (vfio_pci_core_range_intersect_range(pos, count, PCI_SUBSYSTEM_VENDOR_ID, 231 + sizeof(val16), &copy_offset, 232 + &copy_count, &register_offset)) { 210 233 val16 = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET); 211 234 if (copy_to_user(buf + copy_offset, (void *)&val16 + register_offset, 212 235 copy_count)) ··· 249 270 loff_t copy_offset; 250 271 size_t copy_count; 251 272 252 - if (range_intersect_range(pos, count, PCI_COMMAND, sizeof(virtvdev->pci_cmd), 253 - &copy_offset, &copy_count, 254 - &register_offset)) { 273 + if (vfio_pci_core_range_intersect_range(pos, count, PCI_COMMAND, 274 + sizeof(virtvdev->pci_cmd), 275 + &copy_offset, &copy_count, 276 + &register_offset)) { 255 277 if (copy_from_user((void *)&virtvdev->pci_cmd + register_offset, 256 278 buf + copy_offset, 257 279 copy_count)) 258 280 return -EFAULT; 259 281 } 260 282 261 - if (range_intersect_range(pos, count, PCI_BASE_ADDRESS_0, 262 - sizeof(virtvdev->pci_base_addr_0), 263 - &copy_offset, &copy_count, 264 - &register_offset)) { 283 + if (vfio_pci_core_range_intersect_range(pos, count, PCI_BASE_ADDRESS_0, 284 + sizeof(virtvdev->pci_base_addr_0), 285 + &copy_offset, &copy_count, 286 + &register_offset)) { 265 287 if (copy_from_user((void *)&virtvdev->pci_base_addr_0 + register_offset, 266 288 buf + copy_offset, 267 289 copy_count))
+5
include/linux/vfio_pci_core.h
··· 134 134 void __iomem *io, char __user *buf, 135 135 loff_t off, size_t count, size_t x_start, 136 136 size_t x_end, bool iswrite); 137 + bool vfio_pci_core_range_intersect_range(loff_t buf_start, size_t buf_cnt, 138 + loff_t reg_start, size_t reg_cnt, 139 + loff_t *buf_offset, 140 + size_t *intersect_count, 141 + size_t *register_offset); 137 142 #define VFIO_IOWRITE_DECLATION(size) \ 138 143 int vfio_pci_core_iowrite##size(struct vfio_pci_core_device *vdev, \ 139 144 bool test_mem, u##size val, void __iomem *io);