1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * arch/alpha/kernel/pci-sysfs.c 4 * 5 * Copyright (C) 2009 Ivan Kokshaysky 6 * 7 * Alpha PCI resource files. 8 * 9 * Loosely based on generic HAVE_PCI_MMAP implementation in 10 * drivers/pci/pci-sysfs.c 11 */ 12 13 #include <linux/sched.h> 14 #include <linux/security.h> 15 #include <linux/pci.h> 16 17 static int hose_mmap_page_range(struct pci_controller *hose, 18 struct vm_area_struct *vma, 19 enum pci_mmap_state mmap_type, int sparse) 20 { 21 unsigned long base; 22 23 if (mmap_type == pci_mmap_mem) 24 base = sparse ? hose->sparse_mem_base : hose->dense_mem_base; 25 else 26 base = sparse ? hose->sparse_io_base : hose->dense_io_base; 27 28 vma->vm_pgoff += base >> PAGE_SHIFT; 29 30 return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, 31 vma->vm_end - vma->vm_start, 32 vma->vm_page_prot); 33 } 34 35 static int __pci_mmap_fits(struct pci_dev *pdev, int num, 36 struct vm_area_struct *vma, int sparse) 37 { 38 resource_size_t len = pci_resource_len(pdev, num); 39 unsigned long nr, start, size; 40 int shift = sparse ? 5 : 0; 41 42 if (!len) 43 return 0; 44 45 nr = vma_pages(vma); 46 start = vma->vm_pgoff; 47 size = ((len - 1) >> (PAGE_SHIFT - shift)) + 1; 48 49 return start < size && size - start >= nr; 50 } 51 52 /** 53 * pci_mmap_resource - map a PCI resource into user memory space 54 * @kobj: kobject for mapping 55 * @attr: struct bin_attribute for the file being mapped 56 * @vma: struct vm_area_struct passed into the mmap 57 * @sparse: address space type 58 * 59 * Use the bus mapping routines to map a PCI resource into userspace. 60 * 61 * Return: %0 on success, negative error code otherwise 62 */ 63 static int pci_mmap_resource(struct kobject *kobj, 64 const struct bin_attribute *attr, 65 struct vm_area_struct *vma, int sparse) 66 { 67 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 68 int barno = (unsigned long)attr->private; 69 enum pci_mmap_state mmap_type; 70 struct pci_bus_region bar; 71 int ret; 72 73 ret = security_locked_down(LOCKDOWN_PCI_ACCESS); 74 if (ret) 75 return ret; 76 77 if (pci_resource_is_mem(pdev, barno) && 78 iomem_is_exclusive(pci_resource_start(pdev, barno))) 79 return -EINVAL; 80 81 if (!__pci_mmap_fits(pdev, barno, vma, sparse)) 82 return -EINVAL; 83 84 pcibios_resource_to_bus(pdev->bus, &bar, pci_resource_n(pdev, barno)); 85 vma->vm_pgoff += bar.start >> (PAGE_SHIFT - (sparse ? 5 : 0)); 86 mmap_type = pci_resource_is_mem(pdev, barno) ? pci_mmap_mem : pci_mmap_io; 87 88 return hose_mmap_page_range(pdev->sysdata, vma, mmap_type, sparse); 89 } 90 91 static int pci_mmap_resource_sparse(struct file *filp, struct kobject *kobj, 92 const struct bin_attribute *attr, 93 struct vm_area_struct *vma) 94 { 95 return pci_mmap_resource(kobj, attr, vma, 1); 96 } 97 98 static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj, 99 const struct bin_attribute *attr, 100 struct vm_area_struct *vma) 101 { 102 return pci_mmap_resource(kobj, attr, vma, 0); 103 } 104 105 #define __pci_dev_resource_attr(_bar, _name, _suffix, _mmap) \ 106 static const struct bin_attribute \ 107 pci_dev_resource##_bar##_suffix##_attr = { \ 108 .attr = { .name = __stringify(_name), .mode = 0600 }, \ 109 .private = (void *)(unsigned long)(_bar), \ 110 .mmap = (_mmap), \ 111 } 112 113 #define pci_dev_resource_attr(_bar) \ 114 __pci_dev_resource_attr(_bar, resource##_bar,, \ 115 pci_mmap_resource_dense) 116 117 #define pci_dev_resource_sparse_attr(_bar) \ 118 __pci_dev_resource_attr(_bar, resource##_bar##_sparse, _sparse, \ 119 pci_mmap_resource_sparse) 120 121 #define pci_dev_resource_dense_attr(_bar) \ 122 __pci_dev_resource_attr(_bar, resource##_bar##_dense, _dense, \ 123 pci_mmap_resource_dense) 124 125 static int sparse_mem_mmap_fits(struct pci_dev *pdev, int num) 126 { 127 struct pci_bus_region bar; 128 struct pci_controller *hose = pdev->sysdata; 129 long dense_offset; 130 unsigned long sparse_size; 131 132 pcibios_resource_to_bus(pdev->bus, &bar, pci_resource_n(pdev, num)); 133 134 /* All core logic chips have 4G sparse address space, except 135 CIA which has 16G (see xxx_SPARSE_MEM and xxx_DENSE_MEM 136 definitions in asm/core_xxx.h files). This corresponds 137 to 128M or 512M of the bus space. */ 138 dense_offset = (long)(hose->dense_mem_base - hose->sparse_mem_base); 139 sparse_size = dense_offset >= 0x400000000UL ? 0x20000000 : 0x8000000; 140 141 return bar.end < sparse_size; 142 } 143 144 /* Legacy I/O bus mapping stuff. */ 145 146 static int __legacy_mmap_fits(struct vm_area_struct *vma, 147 unsigned long res_size) 148 { 149 unsigned long nr, start, size; 150 151 nr = vma_pages(vma); 152 start = vma->vm_pgoff; 153 size = ((res_size - 1) >> PAGE_SHIFT) + 1; 154 155 return start < size && size - start >= nr; 156 } 157 158 static inline int has_sparse(struct pci_controller *hose, 159 enum pci_mmap_state mmap_type) 160 { 161 unsigned long base; 162 163 base = (mmap_type == pci_mmap_mem) ? hose->sparse_mem_base : 164 hose->sparse_io_base; 165 166 return base != 0; 167 } 168 169 int pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma, 170 enum pci_mmap_state mmap_type) 171 { 172 struct pci_controller *hose = bus->sysdata; 173 int sparse = has_sparse(hose, mmap_type); 174 unsigned long res_size; 175 176 res_size = (mmap_type == pci_mmap_mem) ? PCI_LEGACY_MEM_SIZE : 177 PCI_LEGACY_IO_SIZE; 178 if (sparse) 179 res_size <<= 5; 180 181 if (!__legacy_mmap_fits(vma, res_size)) 182 return -EINVAL; 183 184 return hose_mmap_page_range(hose, vma, mmap_type, sparse); 185 } 186 187 bool pci_legacy_has_sparse(struct pci_bus *bus, enum pci_mmap_state type) 188 { 189 struct pci_controller *hose = bus->sysdata; 190 191 return has_sparse(hose, type); 192 } 193 194 /* Legacy I/O bus read/write functions */ 195 int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val, size_t size) 196 { 197 struct pci_controller *hose = bus->sysdata; 198 199 port += hose->io_space->start; 200 201 switch(size) { 202 case 1: 203 *((u8 *)val) = inb(port); 204 return 1; 205 case 2: 206 if (port & 1) 207 return -EINVAL; 208 *((u16 *)val) = inw(port); 209 return 2; 210 case 4: 211 if (port & 3) 212 return -EINVAL; 213 *((u32 *)val) = inl(port); 214 return 4; 215 } 216 return -EINVAL; 217 } 218 219 int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size) 220 { 221 struct pci_controller *hose = bus->sysdata; 222 223 port += hose->io_space->start; 224 225 switch(size) { 226 case 1: 227 outb(port, val); 228 return 1; 229 case 2: 230 if (port & 1) 231 return -EINVAL; 232 outw(port, val); 233 return 2; 234 case 4: 235 if (port & 3) 236 return -EINVAL; 237 outl(port, val); 238 return 4; 239 } 240 return -EINVAL; 241 } 242 243 pci_dev_resource_attr(0); 244 pci_dev_resource_attr(1); 245 pci_dev_resource_attr(2); 246 pci_dev_resource_attr(3); 247 pci_dev_resource_attr(4); 248 pci_dev_resource_attr(5); 249 250 pci_dev_resource_sparse_attr(0); 251 pci_dev_resource_sparse_attr(1); 252 pci_dev_resource_sparse_attr(2); 253 pci_dev_resource_sparse_attr(3); 254 pci_dev_resource_sparse_attr(4); 255 pci_dev_resource_sparse_attr(5); 256 257 pci_dev_resource_dense_attr(0); 258 pci_dev_resource_dense_attr(1); 259 pci_dev_resource_dense_attr(2); 260 pci_dev_resource_dense_attr(3); 261 pci_dev_resource_dense_attr(4); 262 pci_dev_resource_dense_attr(5); 263 264 static inline enum pci_mmap_state pci_bar_mmap_type(struct pci_dev *pdev, 265 int bar) 266 { 267 return pci_resource_is_mem(pdev, bar) ? pci_mmap_mem : pci_mmap_io; 268 } 269 270 static inline umode_t __pci_resource_attr_is_visible(struct kobject *kobj, 271 const struct bin_attribute *a, 272 int bar) 273 { 274 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 275 276 if (!pci_resource_len(pdev, bar)) 277 return 0; 278 279 return a->attr.mode; 280 } 281 282 static umode_t pci_dev_resource_is_visible(struct kobject *kobj, 283 const struct bin_attribute *a, 284 int bar) 285 { 286 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 287 struct pci_controller *hose = pdev->sysdata; 288 289 if (has_sparse(hose, pci_bar_mmap_type(pdev, bar))) 290 return 0; 291 292 return __pci_resource_attr_is_visible(kobj, a, bar); 293 } 294 295 static umode_t pci_dev_resource_sparse_is_visible(struct kobject *kobj, 296 const struct bin_attribute *a, 297 int bar) 298 { 299 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 300 struct pci_controller *hose = pdev->sysdata; 301 enum pci_mmap_state type = pci_bar_mmap_type(pdev, bar); 302 303 if (!has_sparse(hose, type)) 304 return 0; 305 306 if (type == pci_mmap_mem && !sparse_mem_mmap_fits(pdev, bar)) 307 return 0; 308 309 return __pci_resource_attr_is_visible(kobj, a, bar); 310 } 311 312 static umode_t pci_dev_resource_dense_is_visible(struct kobject *kobj, 313 const struct bin_attribute *a, 314 int bar) 315 { 316 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 317 struct pci_controller *hose = pdev->sysdata; 318 enum pci_mmap_state type = pci_bar_mmap_type(pdev, bar); 319 unsigned long dense_base; 320 321 if (!has_sparse(hose, type)) 322 return 0; 323 324 if (type == pci_mmap_mem && !sparse_mem_mmap_fits(pdev, bar)) 325 return __pci_resource_attr_is_visible(kobj, a, bar); 326 327 dense_base = (type == pci_mmap_mem) ? hose->dense_mem_base : 328 hose->dense_io_base; 329 if (!dense_base) 330 return 0; 331 332 return __pci_resource_attr_is_visible(kobj, a, bar); 333 } 334 335 static inline size_t __pci_dev_resource_bin_size(struct kobject *kobj, 336 int bar, bool sparse) 337 { 338 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 339 size_t size = pci_resource_len(pdev, bar); 340 341 return sparse ? size << 5 : size; 342 } 343 344 static size_t pci_dev_resource_bin_size(struct kobject *kobj, 345 const struct bin_attribute *a, 346 int bar) 347 { 348 return __pci_dev_resource_bin_size(kobj, bar, false); 349 } 350 351 static size_t pci_dev_resource_sparse_bin_size(struct kobject *kobj, 352 const struct bin_attribute *a, 353 int bar) 354 { 355 return __pci_dev_resource_bin_size(kobj, bar, true); 356 } 357 358 static const struct bin_attribute *const pci_dev_resource_attrs[] = { 359 &pci_dev_resource0_attr, 360 &pci_dev_resource1_attr, 361 &pci_dev_resource2_attr, 362 &pci_dev_resource3_attr, 363 &pci_dev_resource4_attr, 364 &pci_dev_resource5_attr, 365 NULL, 366 }; 367 368 static const struct bin_attribute *const pci_dev_resource_sparse_attrs[] = { 369 &pci_dev_resource0_sparse_attr, 370 &pci_dev_resource1_sparse_attr, 371 &pci_dev_resource2_sparse_attr, 372 &pci_dev_resource3_sparse_attr, 373 &pci_dev_resource4_sparse_attr, 374 &pci_dev_resource5_sparse_attr, 375 NULL, 376 }; 377 378 static const struct bin_attribute *const pci_dev_resource_dense_attrs[] = { 379 &pci_dev_resource0_dense_attr, 380 &pci_dev_resource1_dense_attr, 381 &pci_dev_resource2_dense_attr, 382 &pci_dev_resource3_dense_attr, 383 &pci_dev_resource4_dense_attr, 384 &pci_dev_resource5_dense_attr, 385 NULL, 386 }; 387 388 const struct attribute_group pci_dev_resource_attr_group = { 389 .bin_attrs = pci_dev_resource_attrs, 390 .is_bin_visible = pci_dev_resource_is_visible, 391 .bin_size = pci_dev_resource_bin_size, 392 }; 393 394 const struct attribute_group pci_dev_resource_sparse_attr_group = { 395 .bin_attrs = pci_dev_resource_sparse_attrs, 396 .is_bin_visible = pci_dev_resource_sparse_is_visible, 397 .bin_size = pci_dev_resource_sparse_bin_size, 398 }; 399 400 const struct attribute_group pci_dev_resource_dense_attr_group = { 401 .bin_attrs = pci_dev_resource_dense_attrs, 402 .is_bin_visible = pci_dev_resource_dense_is_visible, 403 .bin_size = pci_dev_resource_bin_size, 404 }; 405