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