root/drivers/xen/xen-pciback/conf_space.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. DEFINE_PCI_CONFIG
  2. conf_space_write
  3. get_mask
  4. valid_request
  5. merge_value
  6. xen_pcibios_err_to_errno
  7. xen_pcibk_config_read
  8. xen_pcibk_config_write
  9. xen_pcibk_config_free_dyn_fields
  10. xen_pcibk_config_reset_dev
  11. xen_pcibk_config_free_dev
  12. xen_pcibk_config_add_field_offset
  13. xen_pcibk_config_init_dev
  14. xen_pcibk_config_init

   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 
  20 bool xen_pcibk_permissive;
  21 module_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)                       \
  26 int 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 
  32 DEFINE_PCI_CONFIG(read, byte, u8 *)
  33 DEFINE_PCI_CONFIG(read, word, u16 *)
  34 DEFINE_PCI_CONFIG(read, dword, u32 *)
  35 
  36 DEFINE_PCI_CONFIG(write, byte, u8)
  37 DEFINE_PCI_CONFIG(write, word, u16)
  38 DEFINE_PCI_CONFIG(write, dword, u32)
  39 
  40 static 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 
  68 static 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 
  95 static 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 
 105 static 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 
 113 static 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 
 128 static 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 
 145 int 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 
 197 out:
 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 
 206 int 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 
 289 void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev)
 290 {
 291         struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 292         struct config_field_entry *cfg_entry, *t;
 293         const struct config_field *field;
 294 
 295         dev_dbg(&dev->dev, "free-ing dynamically allocated virtual "
 296                            "configuration space fields\n");
 297         if (!dev_data)
 298                 return;
 299 
 300         list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
 301                 field = cfg_entry->field;
 302 
 303                 if (field->clean) {
 304                         field->clean((struct config_field *)field);
 305 
 306                         kfree(cfg_entry->data);
 307 
 308                         list_del(&cfg_entry->list);
 309                         kfree(cfg_entry);
 310                 }
 311 
 312         }
 313 }
 314 
 315 void xen_pcibk_config_reset_dev(struct pci_dev *dev)
 316 {
 317         struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 318         const struct config_field_entry *cfg_entry;
 319         const struct config_field *field;
 320 
 321         dev_dbg(&dev->dev, "resetting virtual configuration space\n");
 322         if (!dev_data)
 323                 return;
 324 
 325         list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
 326                 field = cfg_entry->field;
 327 
 328                 if (field->reset)
 329                         field->reset(dev, OFFSET(cfg_entry), cfg_entry->data);
 330         }
 331 }
 332 
 333 void xen_pcibk_config_free_dev(struct pci_dev *dev)
 334 {
 335         struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 336         struct config_field_entry *cfg_entry, *t;
 337         const struct config_field *field;
 338 
 339         dev_dbg(&dev->dev, "free-ing virtual configuration space fields\n");
 340         if (!dev_data)
 341                 return;
 342 
 343         list_for_each_entry_safe(cfg_entry, t, &dev_data->config_fields, list) {
 344                 list_del(&cfg_entry->list);
 345 
 346                 field = cfg_entry->field;
 347 
 348                 if (field->release)
 349                         field->release(dev, OFFSET(cfg_entry), cfg_entry->data);
 350 
 351                 kfree(cfg_entry);
 352         }
 353 }
 354 
 355 int xen_pcibk_config_add_field_offset(struct pci_dev *dev,
 356                                     const struct config_field *field,
 357                                     unsigned int base_offset)
 358 {
 359         int err = 0;
 360         struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 361         struct config_field_entry *cfg_entry;
 362         void *tmp;
 363 
 364         cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
 365         if (!cfg_entry) {
 366                 err = -ENOMEM;
 367                 goto out;
 368         }
 369 
 370         cfg_entry->data = NULL;
 371         cfg_entry->field = field;
 372         cfg_entry->base_offset = base_offset;
 373 
 374         /* silently ignore duplicate fields */
 375         err = xen_pcibk_field_is_dup(dev, OFFSET(cfg_entry));
 376         if (err)
 377                 goto out;
 378 
 379         if (field->init) {
 380                 tmp = field->init(dev, OFFSET(cfg_entry));
 381 
 382                 if (IS_ERR(tmp)) {
 383                         err = PTR_ERR(tmp);
 384                         goto out;
 385                 }
 386 
 387                 cfg_entry->data = tmp;
 388         }
 389 
 390         dev_dbg(&dev->dev, "added config field at offset 0x%02x\n",
 391                 OFFSET(cfg_entry));
 392         list_add_tail(&cfg_entry->list, &dev_data->config_fields);
 393 
 394 out:
 395         if (err)
 396                 kfree(cfg_entry);
 397 
 398         return err;
 399 }
 400 
 401 /* This sets up the device's virtual configuration space to keep track of
 402  * certain registers (like the base address registers (BARs) so that we can
 403  * keep the client from manipulating them directly.
 404  */
 405 int xen_pcibk_config_init_dev(struct pci_dev *dev)
 406 {
 407         int err = 0;
 408         struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
 409 
 410         dev_dbg(&dev->dev, "initializing virtual configuration space\n");
 411 
 412         INIT_LIST_HEAD(&dev_data->config_fields);
 413 
 414         err = xen_pcibk_config_header_add_fields(dev);
 415         if (err)
 416                 goto out;
 417 
 418         err = xen_pcibk_config_capability_add_fields(dev);
 419         if (err)
 420                 goto out;
 421 
 422         err = xen_pcibk_config_quirks_init(dev);
 423 
 424 out:
 425         return err;
 426 }
 427 
 428 int xen_pcibk_config_init(void)
 429 {
 430         return xen_pcibk_config_capability_init();
 431 }

/* [<][>][^][v][top][bottom][index][help] */