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

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

DEFINITIONS

This source file includes following definitions.
  1. command_init
  2. command_read
  3. command_write
  4. rom_write
  5. bar_write
  6. bar_read
  7. bar_init
  8. bar_reset
  9. bar_release
  10. xen_pcibk_read_vendor
  11. xen_pcibk_read_device
  12. interrupt_read
  13. bist_write
  14. xen_pcibk_config_header_add_fields

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * PCI Backend - Handles the virtual fields in the configuration space headers.
   4  *
   5  * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
   6  */
   7 
   8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/pci.h>
  12 #include "pciback.h"
  13 #include "conf_space.h"
  14 
  15 struct pci_cmd_info {
  16         u16 val;
  17 };
  18 
  19 struct pci_bar_info {
  20         u32 val;
  21         u32 len_val;
  22         int which;
  23 };
  24 
  25 #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
  26 #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
  27 
  28 /* Bits guests are allowed to control in permissive mode. */
  29 #define PCI_COMMAND_GUEST (PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| \
  30                            PCI_COMMAND_INVALIDATE|PCI_COMMAND_VGA_PALETTE| \
  31                            PCI_COMMAND_WAIT|PCI_COMMAND_FAST_BACK)
  32 
  33 static void *command_init(struct pci_dev *dev, int offset)
  34 {
  35         struct pci_cmd_info *cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
  36         int err;
  37 
  38         if (!cmd)
  39                 return ERR_PTR(-ENOMEM);
  40 
  41         err = pci_read_config_word(dev, PCI_COMMAND, &cmd->val);
  42         if (err) {
  43                 kfree(cmd);
  44                 return ERR_PTR(err);
  45         }
  46 
  47         return cmd;
  48 }
  49 
  50 static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
  51 {
  52         int ret = pci_read_config_word(dev, offset, value);
  53         const struct pci_cmd_info *cmd = data;
  54 
  55         *value &= PCI_COMMAND_GUEST;
  56         *value |= cmd->val & ~PCI_COMMAND_GUEST;
  57 
  58         return ret;
  59 }
  60 
  61 static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
  62 {
  63         struct xen_pcibk_dev_data *dev_data;
  64         int err;
  65         u16 val;
  66         struct pci_cmd_info *cmd = data;
  67 
  68         dev_data = pci_get_drvdata(dev);
  69         if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
  70                 if (unlikely(verbose_request))
  71                         printk(KERN_DEBUG DRV_NAME ": %s: enable\n",
  72                                pci_name(dev));
  73                 err = pci_enable_device(dev);
  74                 if (err)
  75                         return err;
  76                 if (dev_data)
  77                         dev_data->enable_intx = 1;
  78         } else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
  79                 if (unlikely(verbose_request))
  80                         printk(KERN_DEBUG DRV_NAME ": %s: disable\n",
  81                                pci_name(dev));
  82                 pci_disable_device(dev);
  83                 if (dev_data)
  84                         dev_data->enable_intx = 0;
  85         }
  86 
  87         if (!dev->is_busmaster && is_master_cmd(value)) {
  88                 if (unlikely(verbose_request))
  89                         printk(KERN_DEBUG DRV_NAME ": %s: set bus master\n",
  90                                pci_name(dev));
  91                 pci_set_master(dev);
  92         } else if (dev->is_busmaster && !is_master_cmd(value)) {
  93                 if (unlikely(verbose_request))
  94                         printk(KERN_DEBUG DRV_NAME ": %s: clear bus master\n",
  95                                pci_name(dev));
  96                 pci_clear_master(dev);
  97         }
  98 
  99         if (!(cmd->val & PCI_COMMAND_INVALIDATE) &&
 100             (value & PCI_COMMAND_INVALIDATE)) {
 101                 if (unlikely(verbose_request))
 102                         printk(KERN_DEBUG
 103                                DRV_NAME ": %s: enable memory-write-invalidate\n",
 104                                pci_name(dev));
 105                 err = pci_set_mwi(dev);
 106                 if (err) {
 107                         pr_warn("%s: cannot enable memory-write-invalidate (%d)\n",
 108                                 pci_name(dev), err);
 109                         value &= ~PCI_COMMAND_INVALIDATE;
 110                 }
 111         } else if ((cmd->val & PCI_COMMAND_INVALIDATE) &&
 112                    !(value & PCI_COMMAND_INVALIDATE)) {
 113                 if (unlikely(verbose_request))
 114                         printk(KERN_DEBUG
 115                                DRV_NAME ": %s: disable memory-write-invalidate\n",
 116                                pci_name(dev));
 117                 pci_clear_mwi(dev);
 118         }
 119 
 120         cmd->val = value;
 121 
 122         if (!xen_pcibk_permissive && (!dev_data || !dev_data->permissive))
 123                 return 0;
 124 
 125         /* Only allow the guest to control certain bits. */
 126         err = pci_read_config_word(dev, offset, &val);
 127         if (err || val == value)
 128                 return err;
 129 
 130         value &= PCI_COMMAND_GUEST;
 131         value |= val & ~PCI_COMMAND_GUEST;
 132 
 133         return pci_write_config_word(dev, offset, value);
 134 }
 135 
 136 static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
 137 {
 138         struct pci_bar_info *bar = data;
 139 
 140         if (unlikely(!bar)) {
 141                 pr_warn(DRV_NAME ": driver data not found for %s\n",
 142                        pci_name(dev));
 143                 return XEN_PCI_ERR_op_failed;
 144         }
 145 
 146         /* A write to obtain the length must happen as a 32-bit write.
 147          * This does not (yet) support writing individual bytes
 148          */
 149         if ((value | ~PCI_ROM_ADDRESS_MASK) == ~0U)
 150                 bar->which = 1;
 151         else {
 152                 u32 tmpval;
 153                 pci_read_config_dword(dev, offset, &tmpval);
 154                 if (tmpval != bar->val && value == bar->val) {
 155                         /* Allow restoration of bar value. */
 156                         pci_write_config_dword(dev, offset, bar->val);
 157                 }
 158                 bar->which = 0;
 159         }
 160 
 161         /* Do we need to support enabling/disabling the rom address here? */
 162 
 163         return 0;
 164 }
 165 
 166 /* For the BARs, only allow writes which write ~0 or
 167  * the correct resource information
 168  * (Needed for when the driver probes the resource usage)
 169  */
 170 static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
 171 {
 172         struct pci_bar_info *bar = data;
 173         unsigned int pos = (offset - PCI_BASE_ADDRESS_0) / 4;
 174         const struct resource *res = dev->resource;
 175         u32 mask;
 176 
 177         if (unlikely(!bar)) {
 178                 pr_warn(DRV_NAME ": driver data not found for %s\n",
 179                        pci_name(dev));
 180                 return XEN_PCI_ERR_op_failed;
 181         }
 182 
 183         /* A write to obtain the length must happen as a 32-bit write.
 184          * This does not (yet) support writing individual bytes
 185          */
 186         if (res[pos].flags & IORESOURCE_IO)
 187                 mask = ~PCI_BASE_ADDRESS_IO_MASK;
 188         else if (pos && (res[pos - 1].flags & IORESOURCE_MEM_64))
 189                 mask = 0;
 190         else
 191                 mask = ~PCI_BASE_ADDRESS_MEM_MASK;
 192         if ((value | mask) == ~0U)
 193                 bar->which = 1;
 194         else {
 195                 u32 tmpval;
 196                 pci_read_config_dword(dev, offset, &tmpval);
 197                 if (tmpval != bar->val && value == bar->val) {
 198                         /* Allow restoration of bar value. */
 199                         pci_write_config_dword(dev, offset, bar->val);
 200                 }
 201                 bar->which = 0;
 202         }
 203 
 204         return 0;
 205 }
 206 
 207 static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
 208 {
 209         struct pci_bar_info *bar = data;
 210 
 211         if (unlikely(!bar)) {
 212                 pr_warn(DRV_NAME ": driver data not found for %s\n",
 213                        pci_name(dev));
 214                 return XEN_PCI_ERR_op_failed;
 215         }
 216 
 217         *value = bar->which ? bar->len_val : bar->val;
 218 
 219         return 0;
 220 }
 221 
 222 static void *bar_init(struct pci_dev *dev, int offset)
 223 {
 224         unsigned int pos;
 225         const struct resource *res = dev->resource;
 226         struct pci_bar_info *bar = kzalloc(sizeof(*bar), GFP_KERNEL);
 227 
 228         if (!bar)
 229                 return ERR_PTR(-ENOMEM);
 230 
 231         if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1)
 232                 pos = PCI_ROM_RESOURCE;
 233         else {
 234                 pos = (offset - PCI_BASE_ADDRESS_0) / 4;
 235                 if (pos && (res[pos - 1].flags & IORESOURCE_MEM_64)) {
 236                         bar->val = res[pos - 1].start >> 32;
 237                         bar->len_val = -resource_size(&res[pos - 1]) >> 32;
 238                         return bar;
 239                 }
 240         }
 241 
 242         if (!res[pos].flags ||
 243             (res[pos].flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET |
 244                                IORESOURCE_BUSY)))
 245                 return bar;
 246 
 247         bar->val = res[pos].start |
 248                    (res[pos].flags & PCI_REGION_FLAG_MASK);
 249         bar->len_val = -resource_size(&res[pos]) |
 250                        (res[pos].flags & PCI_REGION_FLAG_MASK);
 251 
 252         return bar;
 253 }
 254 
 255 static void bar_reset(struct pci_dev *dev, int offset, void *data)
 256 {
 257         struct pci_bar_info *bar = data;
 258 
 259         bar->which = 0;
 260 }
 261 
 262 static void bar_release(struct pci_dev *dev, int offset, void *data)
 263 {
 264         kfree(data);
 265 }
 266 
 267 static int xen_pcibk_read_vendor(struct pci_dev *dev, int offset,
 268                                u16 *value, void *data)
 269 {
 270         *value = dev->vendor;
 271 
 272         return 0;
 273 }
 274 
 275 static int xen_pcibk_read_device(struct pci_dev *dev, int offset,
 276                                u16 *value, void *data)
 277 {
 278         *value = dev->device;
 279 
 280         return 0;
 281 }
 282 
 283 static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
 284                           void *data)
 285 {
 286         *value = (u8) dev->irq;
 287 
 288         return 0;
 289 }
 290 
 291 static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data)
 292 {
 293         u8 cur_value;
 294         int err;
 295 
 296         err = pci_read_config_byte(dev, offset, &cur_value);
 297         if (err)
 298                 goto out;
 299 
 300         if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START)
 301             || value == PCI_BIST_START)
 302                 err = pci_write_config_byte(dev, offset, value);
 303 
 304 out:
 305         return err;
 306 }
 307 
 308 static const struct config_field header_common[] = {
 309         {
 310          .offset    = PCI_VENDOR_ID,
 311          .size      = 2,
 312          .u.w.read  = xen_pcibk_read_vendor,
 313         },
 314         {
 315          .offset    = PCI_DEVICE_ID,
 316          .size      = 2,
 317          .u.w.read  = xen_pcibk_read_device,
 318         },
 319         {
 320          .offset    = PCI_COMMAND,
 321          .size      = 2,
 322          .init      = command_init,
 323          .release   = bar_release,
 324          .u.w.read  = command_read,
 325          .u.w.write = command_write,
 326         },
 327         {
 328          .offset    = PCI_INTERRUPT_LINE,
 329          .size      = 1,
 330          .u.b.read  = interrupt_read,
 331         },
 332         {
 333          .offset    = PCI_INTERRUPT_PIN,
 334          .size      = 1,
 335          .u.b.read  = xen_pcibk_read_config_byte,
 336         },
 337         {
 338          /* Any side effects of letting driver domain control cache line? */
 339          .offset    = PCI_CACHE_LINE_SIZE,
 340          .size      = 1,
 341          .u.b.read  = xen_pcibk_read_config_byte,
 342          .u.b.write = xen_pcibk_write_config_byte,
 343         },
 344         {
 345          .offset    = PCI_LATENCY_TIMER,
 346          .size      = 1,
 347          .u.b.read  = xen_pcibk_read_config_byte,
 348         },
 349         {
 350          .offset    = PCI_BIST,
 351          .size      = 1,
 352          .u.b.read  = xen_pcibk_read_config_byte,
 353          .u.b.write = bist_write,
 354         },
 355         {}
 356 };
 357 
 358 #define CFG_FIELD_BAR(reg_offset)                       \
 359         {                                               \
 360         .offset     = reg_offset,                       \
 361         .size       = 4,                                \
 362         .init       = bar_init,                         \
 363         .reset      = bar_reset,                        \
 364         .release    = bar_release,                      \
 365         .u.dw.read  = bar_read,                         \
 366         .u.dw.write = bar_write,                        \
 367         }
 368 
 369 #define CFG_FIELD_ROM(reg_offset)                       \
 370         {                                               \
 371         .offset     = reg_offset,                       \
 372         .size       = 4,                                \
 373         .init       = bar_init,                         \
 374         .reset      = bar_reset,                        \
 375         .release    = bar_release,                      \
 376         .u.dw.read  = bar_read,                         \
 377         .u.dw.write = rom_write,                        \
 378         }
 379 
 380 static const struct config_field header_0[] = {
 381         CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
 382         CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
 383         CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
 384         CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
 385         CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
 386         CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
 387         CFG_FIELD_ROM(PCI_ROM_ADDRESS),
 388         {}
 389 };
 390 
 391 static const struct config_field header_1[] = {
 392         CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
 393         CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
 394         CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
 395         {}
 396 };
 397 
 398 int xen_pcibk_config_header_add_fields(struct pci_dev *dev)
 399 {
 400         int err;
 401 
 402         err = xen_pcibk_config_add_fields(dev, header_common);
 403         if (err)
 404                 goto out;
 405 
 406         switch (dev->hdr_type) {
 407         case PCI_HEADER_TYPE_NORMAL:
 408                 err = xen_pcibk_config_add_fields(dev, header_0);
 409                 break;
 410 
 411         case PCI_HEADER_TYPE_BRIDGE:
 412                 err = xen_pcibk_config_add_fields(dev, header_1);
 413                 break;
 414 
 415         default:
 416                 err = -EINVAL;
 417                 pr_err("%s: Unsupported header type %d!\n",
 418                        pci_name(dev), dev->hdr_type);
 419                 break;
 420         }
 421 
 422 out:
 423         return err;
 424 }

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