LCOV - code coverage report
Current view: top level - drivers/pci - proc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 7 171 4.1 %
Date: 2023-08-24 13:40:31 Functions: 1 12 8.3 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Procfs interface for the PCI bus
       4             :  *
       5             :  * Copyright (c) 1997--1999 Martin Mares <mj@ucw.cz>
       6             :  */
       7             : 
       8             : #include <linux/init.h>
       9             : #include <linux/pci.h>
      10             : #include <linux/slab.h>
      11             : #include <linux/module.h>
      12             : #include <linux/proc_fs.h>
      13             : #include <linux/seq_file.h>
      14             : #include <linux/capability.h>
      15             : #include <linux/uaccess.h>
      16             : #include <linux/security.h>
      17             : #include <asm/byteorder.h>
      18             : #include "pci.h"
      19             : 
      20             : static int proc_initialized;    /* = 0 */
      21             : 
      22           0 : static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
      23             : {
      24           0 :         struct pci_dev *dev = pde_data(file_inode(file));
      25           0 :         return fixed_size_llseek(file, off, whence, dev->cfg_size);
      26             : }
      27             : 
      28           0 : static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
      29             :                                  size_t nbytes, loff_t *ppos)
      30             : {
      31           0 :         struct pci_dev *dev = pde_data(file_inode(file));
      32           0 :         unsigned int pos = *ppos;
      33             :         unsigned int cnt, size;
      34             : 
      35             :         /*
      36             :          * Normal users can read only the standardized portion of the
      37             :          * configuration space as several chips lock up when trying to read
      38             :          * undefined locations (think of Intel PIIX4 as a typical example).
      39             :          */
      40             : 
      41           0 :         if (capable(CAP_SYS_ADMIN))
      42           0 :                 size = dev->cfg_size;
      43           0 :         else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
      44             :                 size = 128;
      45             :         else
      46           0 :                 size = 64;
      47             : 
      48           0 :         if (pos >= size)
      49             :                 return 0;
      50           0 :         if (nbytes >= size)
      51           0 :                 nbytes = size;
      52           0 :         if (pos + nbytes > size)
      53           0 :                 nbytes = size - pos;
      54           0 :         cnt = nbytes;
      55             : 
      56           0 :         if (!access_ok(buf, cnt))
      57             :                 return -EINVAL;
      58             : 
      59           0 :         pci_config_pm_runtime_get(dev);
      60             : 
      61           0 :         if ((pos & 1) && cnt) {
      62             :                 unsigned char val;
      63           0 :                 pci_user_read_config_byte(dev, pos, &val);
      64           0 :                 __put_user(val, buf);
      65           0 :                 buf++;
      66           0 :                 pos++;
      67           0 :                 cnt--;
      68             :         }
      69             : 
      70           0 :         if ((pos & 3) && cnt > 2) {
      71             :                 unsigned short val;
      72           0 :                 pci_user_read_config_word(dev, pos, &val);
      73           0 :                 __put_user(cpu_to_le16(val), (__le16 __user *) buf);
      74           0 :                 buf += 2;
      75           0 :                 pos += 2;
      76           0 :                 cnt -= 2;
      77             :         }
      78             : 
      79           0 :         while (cnt >= 4) {
      80             :                 unsigned int val;
      81           0 :                 pci_user_read_config_dword(dev, pos, &val);
      82           0 :                 __put_user(cpu_to_le32(val), (__le32 __user *) buf);
      83           0 :                 buf += 4;
      84           0 :                 pos += 4;
      85           0 :                 cnt -= 4;
      86           0 :                 cond_resched();
      87             :         }
      88             : 
      89           0 :         if (cnt >= 2) {
      90             :                 unsigned short val;
      91           0 :                 pci_user_read_config_word(dev, pos, &val);
      92           0 :                 __put_user(cpu_to_le16(val), (__le16 __user *) buf);
      93           0 :                 buf += 2;
      94           0 :                 pos += 2;
      95           0 :                 cnt -= 2;
      96             :         }
      97             : 
      98           0 :         if (cnt) {
      99             :                 unsigned char val;
     100           0 :                 pci_user_read_config_byte(dev, pos, &val);
     101           0 :                 __put_user(val, buf);
     102           0 :                 pos++;
     103             :         }
     104             : 
     105           0 :         pci_config_pm_runtime_put(dev);
     106             : 
     107           0 :         *ppos = pos;
     108           0 :         return nbytes;
     109             : }
     110             : 
     111           0 : static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
     112             :                                   size_t nbytes, loff_t *ppos)
     113             : {
     114           0 :         struct inode *ino = file_inode(file);
     115           0 :         struct pci_dev *dev = pde_data(ino);
     116           0 :         int pos = *ppos;
     117           0 :         int size = dev->cfg_size;
     118             :         int cnt, ret;
     119             : 
     120           0 :         ret = security_locked_down(LOCKDOWN_PCI_ACCESS);
     121             :         if (ret)
     122             :                 return ret;
     123             : 
     124           0 :         if (pos >= size)
     125             :                 return 0;
     126           0 :         if (nbytes >= size)
     127           0 :                 nbytes = size;
     128           0 :         if (pos + nbytes > size)
     129           0 :                 nbytes = size - pos;
     130           0 :         cnt = nbytes;
     131             : 
     132           0 :         if (!access_ok(buf, cnt))
     133             :                 return -EINVAL;
     134             : 
     135           0 :         pci_config_pm_runtime_get(dev);
     136             : 
     137           0 :         if ((pos & 1) && cnt) {
     138             :                 unsigned char val;
     139           0 :                 __get_user(val, buf);
     140           0 :                 pci_user_write_config_byte(dev, pos, val);
     141           0 :                 buf++;
     142           0 :                 pos++;
     143           0 :                 cnt--;
     144             :         }
     145             : 
     146           0 :         if ((pos & 3) && cnt > 2) {
     147             :                 __le16 val;
     148           0 :                 __get_user(val, (__le16 __user *) buf);
     149           0 :                 pci_user_write_config_word(dev, pos, le16_to_cpu(val));
     150           0 :                 buf += 2;
     151           0 :                 pos += 2;
     152           0 :                 cnt -= 2;
     153             :         }
     154             : 
     155           0 :         while (cnt >= 4) {
     156             :                 __le32 val;
     157           0 :                 __get_user(val, (__le32 __user *) buf);
     158           0 :                 pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
     159           0 :                 buf += 4;
     160           0 :                 pos += 4;
     161           0 :                 cnt -= 4;
     162             :         }
     163             : 
     164           0 :         if (cnt >= 2) {
     165             :                 __le16 val;
     166           0 :                 __get_user(val, (__le16 __user *) buf);
     167           0 :                 pci_user_write_config_word(dev, pos, le16_to_cpu(val));
     168           0 :                 buf += 2;
     169           0 :                 pos += 2;
     170           0 :                 cnt -= 2;
     171             :         }
     172             : 
     173           0 :         if (cnt) {
     174             :                 unsigned char val;
     175           0 :                 __get_user(val, buf);
     176           0 :                 pci_user_write_config_byte(dev, pos, val);
     177           0 :                 pos++;
     178             :         }
     179             : 
     180           0 :         pci_config_pm_runtime_put(dev);
     181             : 
     182           0 :         *ppos = pos;
     183           0 :         i_size_write(ino, dev->cfg_size);
     184           0 :         return nbytes;
     185             : }
     186             : 
     187             : #ifdef HAVE_PCI_MMAP
     188             : struct pci_filp_private {
     189             :         enum pci_mmap_state mmap_state;
     190             :         int write_combine;
     191             : };
     192             : #endif /* HAVE_PCI_MMAP */
     193             : 
     194           0 : static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
     195             :                                unsigned long arg)
     196             : {
     197           0 :         struct pci_dev *dev = pde_data(file_inode(file));
     198             : #ifdef HAVE_PCI_MMAP
     199             :         struct pci_filp_private *fpriv = file->private_data;
     200             : #endif /* HAVE_PCI_MMAP */
     201           0 :         int ret = 0;
     202             : 
     203           0 :         ret = security_locked_down(LOCKDOWN_PCI_ACCESS);
     204             :         if (ret)
     205             :                 return ret;
     206             : 
     207           0 :         switch (cmd) {
     208             :         case PCIIOC_CONTROLLER:
     209           0 :                 ret = pci_domain_nr(dev->bus);
     210           0 :                 break;
     211             : 
     212             : #ifdef HAVE_PCI_MMAP
     213             :         case PCIIOC_MMAP_IS_IO:
     214             :                 if (!arch_can_pci_mmap_io())
     215             :                         return -EINVAL;
     216             :                 fpriv->mmap_state = pci_mmap_io;
     217             :                 break;
     218             : 
     219             :         case PCIIOC_MMAP_IS_MEM:
     220             :                 fpriv->mmap_state = pci_mmap_mem;
     221             :                 break;
     222             : 
     223             :         case PCIIOC_WRITE_COMBINE:
     224             :                 if (arch_can_pci_mmap_wc()) {
     225             :                         if (arg)
     226             :                                 fpriv->write_combine = 1;
     227             :                         else
     228             :                                 fpriv->write_combine = 0;
     229             :                         break;
     230             :                 }
     231             :                 /* If arch decided it can't, fall through... */
     232             :                 fallthrough;
     233             : #endif /* HAVE_PCI_MMAP */
     234             :         default:
     235             :                 ret = -EINVAL;
     236             :                 break;
     237             :         }
     238             : 
     239           0 :         return ret;
     240             : }
     241             : 
     242             : #ifdef HAVE_PCI_MMAP
     243             : static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
     244             : {
     245             :         struct pci_dev *dev = pde_data(file_inode(file));
     246             :         struct pci_filp_private *fpriv = file->private_data;
     247             :         resource_size_t start, end;
     248             :         int i, ret, write_combine = 0, res_bit = IORESOURCE_MEM;
     249             : 
     250             :         if (!capable(CAP_SYS_RAWIO) ||
     251             :             security_locked_down(LOCKDOWN_PCI_ACCESS))
     252             :                 return -EPERM;
     253             : 
     254             :         if (fpriv->mmap_state == pci_mmap_io) {
     255             :                 if (!arch_can_pci_mmap_io())
     256             :                         return -EINVAL;
     257             :                 res_bit = IORESOURCE_IO;
     258             :         }
     259             : 
     260             :         /* Make sure the caller is mapping a real resource for this device */
     261             :         for (i = 0; i < PCI_STD_NUM_BARS; i++) {
     262             :                 if (dev->resource[i].flags & res_bit &&
     263             :                     pci_mmap_fits(dev, i, vma,  PCI_MMAP_PROCFS))
     264             :                         break;
     265             :         }
     266             : 
     267             :         if (i >= PCI_STD_NUM_BARS)
     268             :                 return -ENODEV;
     269             : 
     270             :         if (fpriv->mmap_state == pci_mmap_mem &&
     271             :             fpriv->write_combine) {
     272             :                 if (dev->resource[i].flags & IORESOURCE_PREFETCH)
     273             :                         write_combine = 1;
     274             :                 else
     275             :                         return -EINVAL;
     276             :         }
     277             : 
     278             :         if (dev->resource[i].flags & IORESOURCE_MEM &&
     279             :             iomem_is_exclusive(dev->resource[i].start))
     280             :                 return -EINVAL;
     281             : 
     282             :         pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
     283             : 
     284             :         /* Adjust vm_pgoff to be the offset within the resource */
     285             :         vma->vm_pgoff -= start >> PAGE_SHIFT;
     286             :         ret = pci_mmap_resource_range(dev, i, vma,
     287             :                                   fpriv->mmap_state, write_combine);
     288             :         if (ret < 0)
     289             :                 return ret;
     290             : 
     291             :         return 0;
     292             : }
     293             : 
     294             : static int proc_bus_pci_open(struct inode *inode, struct file *file)
     295             : {
     296             :         struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL);
     297             : 
     298             :         if (!fpriv)
     299             :                 return -ENOMEM;
     300             : 
     301             :         fpriv->mmap_state = pci_mmap_io;
     302             :         fpriv->write_combine = 0;
     303             : 
     304             :         file->private_data = fpriv;
     305             :         file->f_mapping = iomem_get_mapping();
     306             : 
     307             :         return 0;
     308             : }
     309             : 
     310             : static int proc_bus_pci_release(struct inode *inode, struct file *file)
     311             : {
     312             :         kfree(file->private_data);
     313             :         file->private_data = NULL;
     314             : 
     315             :         return 0;
     316             : }
     317             : #endif /* HAVE_PCI_MMAP */
     318             : 
     319             : static const struct proc_ops proc_bus_pci_ops = {
     320             :         .proc_lseek     = proc_bus_pci_lseek,
     321             :         .proc_read      = proc_bus_pci_read,
     322             :         .proc_write     = proc_bus_pci_write,
     323             :         .proc_ioctl     = proc_bus_pci_ioctl,
     324             : #ifdef CONFIG_COMPAT
     325             :         .proc_compat_ioctl = proc_bus_pci_ioctl,
     326             : #endif
     327             : #ifdef HAVE_PCI_MMAP
     328             :         .proc_open      = proc_bus_pci_open,
     329             :         .proc_release   = proc_bus_pci_release,
     330             :         .proc_mmap      = proc_bus_pci_mmap,
     331             : #ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA
     332             :         .proc_get_unmapped_area = get_pci_unmapped_area,
     333             : #endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */
     334             : #endif /* HAVE_PCI_MMAP */
     335             : };
     336             : 
     337             : /* iterator */
     338           0 : static void *pci_seq_start(struct seq_file *m, loff_t *pos)
     339             : {
     340           0 :         struct pci_dev *dev = NULL;
     341           0 :         loff_t n = *pos;
     342             : 
     343           0 :         for_each_pci_dev(dev) {
     344           0 :                 if (!n--)
     345             :                         break;
     346             :         }
     347           0 :         return dev;
     348             : }
     349             : 
     350           0 : static void *pci_seq_next(struct seq_file *m, void *v, loff_t *pos)
     351             : {
     352           0 :         struct pci_dev *dev = v;
     353             : 
     354           0 :         (*pos)++;
     355           0 :         dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
     356           0 :         return dev;
     357             : }
     358             : 
     359           0 : static void pci_seq_stop(struct seq_file *m, void *v)
     360             : {
     361           0 :         if (v) {
     362           0 :                 struct pci_dev *dev = v;
     363           0 :                 pci_dev_put(dev);
     364             :         }
     365           0 : }
     366             : 
     367           0 : static int show_device(struct seq_file *m, void *v)
     368             : {
     369           0 :         const struct pci_dev *dev = v;
     370             :         const struct pci_driver *drv;
     371             :         int i;
     372             : 
     373           0 :         if (dev == NULL)
     374             :                 return 0;
     375             : 
     376           0 :         drv = pci_dev_driver(dev);
     377           0 :         seq_printf(m, "%02x%02x\t%04x%04x\t%x",
     378           0 :                         dev->bus->number,
     379             :                         dev->devfn,
     380           0 :                         dev->vendor,
     381           0 :                         dev->device,
     382             :                         dev->irq);
     383             : 
     384             :         /* only print standard and ROM resources to preserve compatibility */
     385           0 :         for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
     386             :                 resource_size_t start, end;
     387           0 :                 pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
     388           0 :                 seq_printf(m, "\t%16llx",
     389             :                         (unsigned long long)(start |
     390           0 :                         (dev->resource[i].flags & PCI_REGION_FLAG_MASK)));
     391             :         }
     392           0 :         for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
     393             :                 resource_size_t start, end;
     394           0 :                 pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
     395           0 :                 seq_printf(m, "\t%16llx",
     396           0 :                         dev->resource[i].start < dev->resource[i].end ?
     397           0 :                         (unsigned long long)(end - start) + 1 : 0);
     398             :         }
     399           0 :         seq_putc(m, '\t');
     400           0 :         if (drv)
     401           0 :                 seq_puts(m, drv->name);
     402           0 :         seq_putc(m, '\n');
     403           0 :         return 0;
     404             : }
     405             : 
     406             : static const struct seq_operations proc_bus_pci_devices_op = {
     407             :         .start  = pci_seq_start,
     408             :         .next   = pci_seq_next,
     409             :         .stop   = pci_seq_stop,
     410             :         .show   = show_device
     411             : };
     412             : 
     413             : static struct proc_dir_entry *proc_bus_pci_dir;
     414             : 
     415           0 : int pci_proc_attach_device(struct pci_dev *dev)
     416             : {
     417           0 :         struct pci_bus *bus = dev->bus;
     418             :         struct proc_dir_entry *e;
     419             :         char name[16];
     420             : 
     421           0 :         if (!proc_initialized)
     422             :                 return -EACCES;
     423             : 
     424           0 :         if (!bus->procdir) {
     425           0 :                 if (pci_proc_domain(bus)) {
     426             :                         sprintf(name, "%04x:%02x", pci_domain_nr(bus),
     427             :                                         bus->number);
     428             :                 } else {
     429           0 :                         sprintf(name, "%02x", bus->number);
     430             :                 }
     431           0 :                 bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
     432           0 :                 if (!bus->procdir)
     433             :                         return -ENOMEM;
     434             :         }
     435             : 
     436           0 :         sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
     437           0 :         e = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir,
     438             :                              &proc_bus_pci_ops, dev);
     439           0 :         if (!e)
     440             :                 return -ENOMEM;
     441           0 :         proc_set_size(e, dev->cfg_size);
     442           0 :         dev->procent = e;
     443             : 
     444           0 :         return 0;
     445             : }
     446             : 
     447           0 : int pci_proc_detach_device(struct pci_dev *dev)
     448             : {
     449           0 :         proc_remove(dev->procent);
     450           0 :         dev->procent = NULL;
     451           0 :         return 0;
     452             : }
     453             : 
     454           0 : int pci_proc_detach_bus(struct pci_bus *bus)
     455             : {
     456           0 :         proc_remove(bus->procdir);
     457           0 :         return 0;
     458             : }
     459             : 
     460           1 : static int __init pci_proc_init(void)
     461             : {
     462           1 :         struct pci_dev *dev = NULL;
     463           1 :         proc_bus_pci_dir = proc_mkdir("bus/pci", NULL);
     464           1 :         proc_create_seq("devices", 0, proc_bus_pci_dir,
     465             :                     &proc_bus_pci_devices_op);
     466           1 :         proc_initialized = 1;
     467           2 :         for_each_pci_dev(dev)
     468           0 :                 pci_proc_attach_device(dev);
     469             : 
     470           1 :         return 0;
     471             : }
     472             : device_initcall(pci_proc_init);

Generated by: LCOV version 1.14