linux/drivers/xen/xen-pciback/conf_space.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * PCI Backend - Functions for creating a virtual configuration space for
   4 *               exported PCI Devices.
   5 *               It's dangerous to allow PCI Driver Domains to change their
   6 *               device's resources (memory, i/o ports, interrupts). We need to
   7 *               restrict changes to certain PCI Configuration registers:
   8 *               BARs, INTERRUPT_PIN, most registers in the header...
   9 *
  10 * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
  11 */
  12
  13#include <linux/kernel.h>
  14#include <linux/moduleparam.h>
  15#include <linux/pci.h>
  16#include "pciback.h"
  17#include "conf_space.h"
  18#include "conf_space_quirks.h"
  19
  20bool xen_pcibk_permissive;
  21module_param_named(permissive, xen_pcibk_permissive, bool, 0644);
  22
  23/* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
  24 * xen_pcibk_write_config_word, and xen_pcibk_write_config_byte are created. */
  25#define DEFINE_PCI_CONFIG(op, size, type)                       \
  26int xen_pcibk_##op##_config_##size                              \
  27(struct pci_dev *dev, int offset, type value, void *data)       \
  28{                                                               \
  29        return pci_##op##_config_##size(dev, offset, value);    \
  30}
  31
  32DEFINE_PCI_CONFIG(read, byte, u8 *)
  33DEFINE_PCI_CONFIG(read, word, u16 *)
  34DEFINE_PCI_CONFIG(read, dword, u32 *)
  35
  36DEFINE_PCI_CONFIG(write, byte, u8)
  37DEFINE_PCI_CONFIG(write, word, u16)
  38DEFINE_PCI_CONFIG(write, dword, u32)
  39
  40static int conf_space_read(struct pci_dev *dev,
  41                           const struct config_field_entry *entry,
  42                           int offset, u32 *value)
  43{
  44        int ret = 0;
  45        const struct config_field *field = entry->field;
  46
  47        *value = 0;
  48
  49        switch (field->size) {
  50        case 1:
  51                if (field->u.b.read)
  52                        ret = field->u.b.read(dev, offset, (u8 *) value,
  53                                              entry->data);
  54                break;
  55        case 2:
  56                if (field->u.w.read)
  57                        ret = field->u.w.read(dev, offset, (u16 *) value,
  58                                              entry->data);
  59                break;
  60        case 4:
  61                if (field->u.dw.read)
  62                        ret = field->u.dw.read(dev, offset, value, entry->data);
  63                break;
  64        }
  65        return ret;
  66}
  67
  68static int conf_space_write(struct pci_dev *dev,
  69                            const struct config_field_entry *entry,
  70                            int offset, u32 value)
  71{
  72        int ret = 0;
  73        const struct config_field *field = entry->field;
  74
  75        switch (field->size) {
  76        case 1:
  77                if (field->u.b.write)
  78                        ret = field->u.b.write(dev, offset, (u8) value,
  79                                               entry->data);
  80                break;
  81        case 2:
  82                if (field->u.w.write)
  83                        ret = field->u.w.write(dev, offset, (u16) value,
  84                                               entry->data);
  85                break;
  86        case 4:
  87                if (field->u.dw.write)
  88                        ret = field->u.dw.write(dev, offset, value,
  89                                                entry->data);
  90                break;
  91        }
  92        return ret;
  93}
  94
  95static inline u32 get_mask(int size)
  96{
  97        if (size == 1)
  98                return 0xff;
  99        else if (size == 2)
 100                return 0xffff;
 101        else
 102                return 0xffffffff;
 103}
 104
 105static inline int valid_request(int offset, int size)
 106{
 107        /* Validate request (no un-aligned requests) */
 108        if ((size == 1 || size == 2 || size == 4) && (offset % size) == 0)
 109                return 1;
 110        return 0;
 111}
 112
 113static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
 114                              int offset)
 115{
 116        if (offset >= 0) {
 117                new_val_mask <<= (offset * 8);
 118                new_val <<= (offset * 8);
 119        } else {
 120                new_val_mask >>= (offset * -8);
 121                new_val >>= (offset * -8);
 122        }
 123        val = (val & ~new_val_mask) | (new_val & new_val_mask);
 124
 125        return val;
 126}
 127
 128static int xen_pcibios_err_to_errno(int err)
 129{
 130        switch (err) {
 131        case PCIBIOS_SUCCESSFUL:
 132                return XEN_PCI_ERR_success;
 133        case PCIBIOS_DEVICE_NOT_FOUND:
 134                return XEN_PCI_ERR_dev_not_found;
 135        case PCIBIOS_BAD_REGISTER_NUMBER:
 136                return XEN_PCI_ERR_invalid_offset;
 137        case PCIBIOS_FUNC_NOT_SUPPORTED:
 138                return XEN_PCI_ERR_not_implemented;
 139        case PCIBIOS_SET_FAILED:
 140                return XEN_PCI_ERR_access_denied;
 141        }
 142        return err;
 143}
 144
 145int xen_pcibk_config_read(struct pci_dev *dev, int offset, int size,
 146                          u32 *ret_val)
 147{
 148        int err = 0;
 149        struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 150        const struct config_field_entry *cfg_entry;
 151        const struct config_field *field;
 152        int field_start, field_end;
 153        /* if read fails for any reason, return 0
 154         * (as if device didn't respond) */
 155        u32 value = 0, tmp_val;
 156
 157        if (unlikely(verbose_request))
 158                printk(KERN_DEBUG DRV_NAME ": %s: read %d bytes at 0x%x\n",
 159                       pci_name(dev), size, offset);
 160
 161        if (!valid_request(offset, size)) {
 162                err = XEN_PCI_ERR_invalid_offset;
 163                goto out;
 164        }
 165
 166        /* Get the real value first, then modify as appropriate */
 167        switch (size) {
 168        case 1:
 169                err = pci_read_config_byte(dev, offset, (u8 *) &value);
 170                break;
 171        case 2:
 172                err = pci_read_config_word(dev, offset, (u16 *) &value);
 173                break;
 174        case 4:
 175                err = pci_read_config_dword(dev, offset, &value);
 176                break;
 177        }
 178
 179        list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
 180                field = cfg_entry->field;
 181
 182                field_start = OFFSET(cfg_entry);
 183                field_end = OFFSET(cfg_entry) + field->size;
 184
 185                if (offset + size > field_start && field_end > offset) {
 186                        err = conf_space_read(dev, cfg_entry, field_start,
 187                                              &tmp_val);
 188                        if (err)
 189                                goto out;
 190
 191                        value = merge_value(value, tmp_val,
 192                                            get_mask(field->size),
 193                                            field_start - offset);
 194                }
 195        }
 196
 197out:
 198        if (unlikely(verbose_request))
 199                printk(KERN_DEBUG DRV_NAME ": %s: read %d bytes at 0x%x = %x\n",
 200                       pci_name(dev), size, offset, value);
 201
 202        *ret_val = value;
 203        return xen_pcibios_err_to_errno(err);
 204}
 205
 206int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
 207{
 208        int err = 0, handled = 0;
 209        struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 210        const struct config_field_entry *cfg_entry;
 211        const struct config_field *field;
 212        u32 tmp_val;
 213        int field_start, field_end;
 214
 215        if (unlikely(verbose_request))
 216                printk(KERN_DEBUG
 217                       DRV_NAME ": %s: write request %d bytes at 0x%x = %x\n",
 218                       pci_name(dev), size, offset, value);
 219
 220        if (!valid_request(offset, size))
 221                return XEN_PCI_ERR_invalid_offset;
 222
 223        list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
 224                field = cfg_entry->field;
 225
 226                field_start = OFFSET(cfg_entry);
 227                field_end = OFFSET(cfg_entry) + field->size;
 228
 229                if (offset + size > field_start && field_end > offset) {
 230                        err = conf_space_read(dev, cfg_entry, field_start,
 231                                              &tmp_val);
 232                        if (err)
 233                                break;
 234
 235                        tmp_val = merge_value(tmp_val, value, get_mask(size),
 236                                              offset - field_start);
 237
 238                        err = conf_space_write(dev, cfg_entry, field_start,
 239                                               tmp_val);
 240
 241                        /* handled is set true here, but not every byte
 242                         * may have been written! Properly detecting if
 243                         * every byte is handled is unnecessary as the
 244                         * flag is used to detect devices that need
 245                         * special helpers to work correctly.
 246                         */
 247                        handled = 1;
 248                }
 249        }
 250
 251        if (!handled && !err) {
 252                /* By default, anything not specificially handled above is
 253                 * read-only. The permissive flag changes this behavior so
 254                 * that anything not specifically handled above is writable.
 255                 * This means that some fields may still be read-only because
 256                 * they have entries in the config_field list that intercept
 257                 * the write and do nothing. */
 258                if (dev_data->permissive || xen_pcibk_permissive) {
 259                        switch (size) {
 260                        case 1:
 261                                err = pci_write_config_byte(dev, offset,
 262                                                            (u8) value);
 263                                break;
 264                        case 2:
 265                                err = pci_write_config_word(dev, offset,
 266                                                            (u16) value);
 267                                break;
 268                        case 4:
 269                                err = pci_write_config_dword(dev, offset,
 270                                                             (u32) value);
 271                                break;
 272                        }
 273                } else if (!dev_data->warned_on_write) {
 274                        dev_data->warned_on_write = 1;
 275                        dev_warn(&dev->dev, "Driver tried to write to a "
 276                                 "read-only configuration space field at offset"
 277                                 " 0x%x, size %d. This may be harmless, but if "
 278                                 "you have problems with your device:\n"
 279                                 "1) see permissive attribute in sysfs\n"
 280                                 "2) report problems to the xen-devel "
 281                                 "mailing list along with details of your "
 282                                 "device obtained from lspci.\n", offset, size);
 283                }
 284        }
 285
 286        return xen_pcibios_err_to_errno(err);
 287}
 288
 289int xen_pcibk_get_interrupt_type(struct pci_dev *dev)
 290{
 291        int err;
 292        u16 val;
 293        int ret = 0;
 294
 295        err = pci_read_config_word(dev, PCI_COMMAND, &val);
 296        if (err)
 297                return err;
 298        if (!(val & PCI_COMMAND_INTX_DISABLE))
 299                ret |= INTERRUPT_TYPE_INTX;
 300
 301        /*
 302         * Do not trust dev->msi(x)_enabled here, as enabling could be done
 303         * bypassing the pci_*msi* functions, by the qemu.
 304         */
 305        if (dev->msi_cap) {
 306                err = pci_read_config_word(dev,
 307                                dev->msi_cap + PCI_MSI_FLAGS,
 308                                &val);
 309                if (err)
 310                        return err;
 311                if (val & PCI_MSI_FLAGS_ENABLE)
 312                        ret |= INTERRUPT_TYPE_MSI;
 313        }
 314        if (dev->msix_cap) {
 315                err = pci_read_config_word(dev,
 316                                dev->msix_cap + PCI_MSIX_FLAGS,
 317                                &val);
 318                if (err)
 319                        return err;
 320                if (val & PCI_MSIX_FLAGS_ENABLE)
 321                        ret |= INTERRUPT_TYPE_MSIX;
 322        }
 323        return ret;
 324}
 325
 326void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev)
 327{
 328        struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 329        struct config_field_entry *cfg_entry, *t;
 330        const struct config_field *field;
 331
 332        dev_dbg(&dev->dev, "free-ing dynamically allocated virtual "
 333                           "configuration space fields\n");
 334        if (!dev_data)
 335                return;
 336
 337        list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
 338                field = cfg_entry->field;
 339
 340                if (field->clean) {
 341                        field->clean((struct config_field *)field);
 342
 343                        kfree(cfg_entry->data);
 344
 345                        list_del(&cfg_entry->list);
 346                        kfree(cfg_entry);
 347                }
 348
 349        }
 350}
 351
 352void xen_pcibk_config_reset_dev(struct pci_dev *dev)
 353{
 354        struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 355        const struct config_field_entry *cfg_entry;
 356        const struct config_field *field;
 357
 358        dev_dbg(&dev->dev, "resetting virtual configuration space\n");
 359        if (!dev_data)
 360                return;
 361
 362        list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
 363                field = cfg_entry->field;
 364
 365                if (field->reset)
 366                        field->reset(dev, OFFSET(cfg_entry), cfg_entry->data);
 367        }
 368}
 369
 370void xen_pcibk_config_free_dev(struct pci_dev *dev)
 371{
 372        struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 373        struct config_field_entry *cfg_entry, *t;
 374        const struct config_field *field;
 375
 376        dev_dbg(&dev->dev, "free-ing virtual configuration space fields\n");
 377        if (!dev_data)
 378                return;
 379
 380        list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
 381                list_del(&cfg_entry->list);
 382
 383                field = cfg_entry->field;
 384
 385                if (field->release)
 386                        field->release(dev, OFFSET(cfg_entry), cfg_entry->data);
 387
 388                kfree(cfg_entry);
 389        }
 390}
 391
 392int xen_pcibk_config_add_field_offset(struct pci_dev *dev,
 393                                    const struct config_field *field,
 394                                    unsigned int base_offset)
 395{
 396        int err = 0;
 397        struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 398        struct config_field_entry *cfg_entry;
 399        void *tmp;
 400
 401        cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
 402        if (!cfg_entry) {
 403                err = -ENOMEM;
 404                goto out;
 405        }
 406
 407        cfg_entry->data = NULL;
 408        cfg_entry->field = field;
 409        cfg_entry->base_offset = base_offset;
 410
 411        /* silently ignore duplicate fields */
 412        err = xen_pcibk_field_is_dup(dev, OFFSET(cfg_entry));
 413        if (err)
 414                goto out;
 415
 416        if (field->init) {
 417                tmp = field->init(dev, OFFSET(cfg_entry));
 418
 419                if (IS_ERR(tmp)) {
 420                        err = PTR_ERR(tmp);
 421                        goto out;
 422                }
 423
 424                cfg_entry->data = tmp;
 425        }
 426
 427        dev_dbg(&dev->dev, "added config field at offset 0x%02x\n",
 428                OFFSET(cfg_entry));
 429        list_add_tail(&cfg_entry->list, &dev_data->config_fields);
 430
 431out:
 432        if (err)
 433                kfree(cfg_entry);
 434
 435        return err;
 436}
 437
 438/* This sets up the device's virtual configuration space to keep track of
 439 * certain registers (like the base address registers (BARs) so that we can
 440 * keep the client from manipulating them directly.
 441 */
 442int xen_pcibk_config_init_dev(struct pci_dev *dev)
 443{
 444        int err = 0;
 445        struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 446
 447        dev_dbg(&dev->dev, "initializing virtual configuration space\n");
 448
 449        INIT_LIST_HEAD(&dev_data->config_fields);
 450
 451        err = xen_pcibk_config_header_add_fields(dev);
 452        if (err)
 453                goto out;
 454
 455        err = xen_pcibk_config_capability_add_fields(dev);
 456        if (err)
 457                goto out;
 458
 459        err = xen_pcibk_config_quirks_init(dev);
 460
 461out:
 462        return err;
 463}
 464
 465int xen_pcibk_config_init(void)
 466{
 467        return xen_pcibk_config_capability_init();
 468}
 469