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