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: 2022-12-09 01:23:36 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             :         int i, ret, write_combine = 0, res_bit = IORESOURCE_MEM;
     248             : 
     249             :         if (!capable(CAP_SYS_RAWIO) ||
     250             :             security_locked_down(LOCKDOWN_PCI_ACCESS))
     251             :                 return -EPERM;
     252             : 
     253             :         if (fpriv->mmap_state == pci_mmap_io) {
     254             :                 if (!arch_can_pci_mmap_io())
     255             :                         return -EINVAL;
     256             :                 res_bit = IORESOURCE_IO;
     257             :         }
     258             : 
     259             :         /* Make sure the caller is mapping a real resource for this device */
     260             :         for (i = 0; i < PCI_STD_NUM_BARS; i++) {
     261             :                 if (dev->resource[i].flags & res_bit &&
     262             :                     pci_mmap_fits(dev, i, vma,  PCI_MMAP_PROCFS))
     263             :                         break;
     264             :         }
     265             : 
     266             :         if (i >= PCI_STD_NUM_BARS)
     267             :                 return -ENODEV;
     268             : 
     269             :         if (fpriv->mmap_state == pci_mmap_mem &&
     270             :             fpriv->write_combine) {
     271             :                 if (dev->resource[i].flags & IORESOURCE_PREFETCH)
     272             :                         write_combine = 1;
     273             :                 else
     274             :                         return -EINVAL;
     275             :         }
     276             : 
     277             :         if (dev->resource[i].flags & IORESOURCE_MEM &&
     278             :             iomem_is_exclusive(dev->resource[i].start))
     279             :                 return -EINVAL;
     280             : 
     281             :         ret = pci_mmap_page_range(dev, i, vma,
     282             :                                   fpriv->mmap_state, write_combine);
     283             :         if (ret < 0)
     284             :                 return ret;
     285             : 
     286             :         return 0;
     287             : }
     288             : 
     289             : static int proc_bus_pci_open(struct inode *inode, struct file *file)
     290             : {
     291             :         struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL);
     292             : 
     293             :         if (!fpriv)
     294             :                 return -ENOMEM;
     295             : 
     296             :         fpriv->mmap_state = pci_mmap_io;
     297             :         fpriv->write_combine = 0;
     298             : 
     299             :         file->private_data = fpriv;
     300             :         file->f_mapping = iomem_get_mapping();
     301             : 
     302             :         return 0;
     303             : }
     304             : 
     305             : static int proc_bus_pci_release(struct inode *inode, struct file *file)
     306             : {
     307             :         kfree(file->private_data);
     308             :         file->private_data = NULL;
     309             : 
     310             :         return 0;
     311             : }
     312             : #endif /* HAVE_PCI_MMAP */
     313             : 
     314             : static const struct proc_ops proc_bus_pci_ops = {
     315             :         .proc_lseek     = proc_bus_pci_lseek,
     316             :         .proc_read      = proc_bus_pci_read,
     317             :         .proc_write     = proc_bus_pci_write,
     318             :         .proc_ioctl     = proc_bus_pci_ioctl,
     319             : #ifdef CONFIG_COMPAT
     320             :         .proc_compat_ioctl = proc_bus_pci_ioctl,
     321             : #endif
     322             : #ifdef HAVE_PCI_MMAP
     323             :         .proc_open      = proc_bus_pci_open,
     324             :         .proc_release   = proc_bus_pci_release,
     325             :         .proc_mmap      = proc_bus_pci_mmap,
     326             : #ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA
     327             :         .proc_get_unmapped_area = get_pci_unmapped_area,
     328             : #endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */
     329             : #endif /* HAVE_PCI_MMAP */
     330             : };
     331             : 
     332             : /* iterator */
     333           0 : static void *pci_seq_start(struct seq_file *m, loff_t *pos)
     334             : {
     335           0 :         struct pci_dev *dev = NULL;
     336           0 :         loff_t n = *pos;
     337             : 
     338           0 :         for_each_pci_dev(dev) {
     339           0 :                 if (!n--)
     340             :                         break;
     341             :         }
     342           0 :         return dev;
     343             : }
     344             : 
     345           0 : static void *pci_seq_next(struct seq_file *m, void *v, loff_t *pos)
     346             : {
     347           0 :         struct pci_dev *dev = v;
     348             : 
     349           0 :         (*pos)++;
     350           0 :         dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
     351           0 :         return dev;
     352             : }
     353             : 
     354           0 : static void pci_seq_stop(struct seq_file *m, void *v)
     355             : {
     356           0 :         if (v) {
     357           0 :                 struct pci_dev *dev = v;
     358           0 :                 pci_dev_put(dev);
     359             :         }
     360           0 : }
     361             : 
     362           0 : static int show_device(struct seq_file *m, void *v)
     363             : {
     364           0 :         const struct pci_dev *dev = v;
     365             :         const struct pci_driver *drv;
     366             :         int i;
     367             : 
     368           0 :         if (dev == NULL)
     369             :                 return 0;
     370             : 
     371           0 :         drv = pci_dev_driver(dev);
     372           0 :         seq_printf(m, "%02x%02x\t%04x%04x\t%x",
     373           0 :                         dev->bus->number,
     374             :                         dev->devfn,
     375           0 :                         dev->vendor,
     376           0 :                         dev->device,
     377             :                         dev->irq);
     378             : 
     379             :         /* only print standard and ROM resources to preserve compatibility */
     380           0 :         for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
     381             :                 resource_size_t start, end;
     382           0 :                 pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
     383           0 :                 seq_printf(m, "\t%16llx",
     384             :                         (unsigned long long)(start |
     385           0 :                         (dev->resource[i].flags & PCI_REGION_FLAG_MASK)));
     386             :         }
     387           0 :         for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
     388             :                 resource_size_t start, end;
     389           0 :                 pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
     390           0 :                 seq_printf(m, "\t%16llx",
     391           0 :                         dev->resource[i].start < dev->resource[i].end ?
     392           0 :                         (unsigned long long)(end - start) + 1 : 0);
     393             :         }
     394           0 :         seq_putc(m, '\t');
     395           0 :         if (drv)
     396           0 :                 seq_puts(m, drv->name);
     397           0 :         seq_putc(m, '\n');
     398           0 :         return 0;
     399             : }
     400             : 
     401             : static const struct seq_operations proc_bus_pci_devices_op = {
     402             :         .start  = pci_seq_start,
     403             :         .next   = pci_seq_next,
     404             :         .stop   = pci_seq_stop,
     405             :         .show   = show_device
     406             : };
     407             : 
     408             : static struct proc_dir_entry *proc_bus_pci_dir;
     409             : 
     410           0 : int pci_proc_attach_device(struct pci_dev *dev)
     411             : {
     412           0 :         struct pci_bus *bus = dev->bus;
     413             :         struct proc_dir_entry *e;
     414             :         char name[16];
     415             : 
     416           0 :         if (!proc_initialized)
     417             :                 return -EACCES;
     418             : 
     419           0 :         if (!bus->procdir) {
     420           0 :                 if (pci_proc_domain(bus)) {
     421             :                         sprintf(name, "%04x:%02x", pci_domain_nr(bus),
     422             :                                         bus->number);
     423             :                 } else {
     424           0 :                         sprintf(name, "%02x", bus->number);
     425             :                 }
     426           0 :                 bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
     427           0 :                 if (!bus->procdir)
     428             :                         return -ENOMEM;
     429             :         }
     430             : 
     431           0 :         sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
     432           0 :         e = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir,
     433             :                              &proc_bus_pci_ops, dev);
     434           0 :         if (!e)
     435             :                 return -ENOMEM;
     436           0 :         proc_set_size(e, dev->cfg_size);
     437           0 :         dev->procent = e;
     438             : 
     439           0 :         return 0;
     440             : }
     441             : 
     442           0 : int pci_proc_detach_device(struct pci_dev *dev)
     443             : {
     444           0 :         proc_remove(dev->procent);
     445           0 :         dev->procent = NULL;
     446           0 :         return 0;
     447             : }
     448             : 
     449           0 : int pci_proc_detach_bus(struct pci_bus *bus)
     450             : {
     451           0 :         proc_remove(bus->procdir);
     452           0 :         return 0;
     453             : }
     454             : 
     455           1 : static int __init pci_proc_init(void)
     456             : {
     457           1 :         struct pci_dev *dev = NULL;
     458           1 :         proc_bus_pci_dir = proc_mkdir("bus/pci", NULL);
     459           1 :         proc_create_seq("devices", 0, proc_bus_pci_dir,
     460             :                     &proc_bus_pci_devices_op);
     461           1 :         proc_initialized = 1;
     462           2 :         for_each_pci_dev(dev)
     463           0 :                 pci_proc_attach_device(dev);
     464             : 
     465           1 :         return 0;
     466             : }
     467             : device_initcall(pci_proc_init);

Generated by: LCOV version 1.14