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