Commit b7ee1603c16c1feb0d439d2ddf6cf824119d0aab

Authored by Michael S. Tsirkin
Committed by Anthony Liguori
1 parent 1b64fcae

qemu/pci: make default_write_config use mask table

Change much of hw/pci to use symbolic constants and a table-driven
design: add a mask table with writable bits set and readonly bits unset.
Detect change by comparing original and new registers.

This makes it easy to support capabilities where read-only/writeable
bit layout differs between devices, depending on capabilities present.

As a result, writing a single byte in BAR registers now works as
it should. Writing to upper limit registers in the bridge
also works as it should. Code is also shorter.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 2 changed files with 46 additions and 117 deletions
hw/pci.c
... ... @@ -255,6 +255,17 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
255 255 return pci_find_bus(bus);
256 256 }
257 257  
  258 +static void pci_init_wmask(PCIDevice *dev)
  259 +{
  260 + int i;
  261 + dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff;
  262 + dev->wmask[PCI_INTERRUPT_LINE] = 0xff;
  263 + dev->wmask[PCI_COMMAND] = PCI_COMMAND_IO | PCI_COMMAND_MEMORY
  264 + | PCI_COMMAND_MASTER;
  265 + for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i)
  266 + dev->wmask[i] = 0xff;
  267 +}
  268 +
258 269 /* -1 for devfn means auto assign */
259 270 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
260 271 const char *name, int devfn,
... ... @@ -276,6 +287,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
276 287 pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
277 288 memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
278 289 pci_set_default_subsystem_id(pci_dev);
  290 + pci_init_wmask(pci_dev);
279 291  
280 292 if (!config_read)
281 293 config_read = pci_default_read_config;
... ... @@ -347,6 +359,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
347 359 {
348 360 PCIIORegion *r;
349 361 uint32_t addr;
  362 + uint32_t wmask;
350 363  
351 364 if ((unsigned int)region_num >= PCI_NUM_REGIONS)
352 365 return;
... ... @@ -362,12 +375,17 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
362 375 r->size = size;
363 376 r->type = type;
364 377 r->map_func = map_func;
  378 +
  379 + wmask = ~(size - 1);
365 380 if (region_num == PCI_ROM_SLOT) {
366 381 addr = 0x30;
  382 + /* ROM enable bit is writeable */
  383 + wmask |= 1;
367 384 } else {
368 385 addr = 0x10 + region_num * 4;
369 386 }
370 387 *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
  388 + *(uint32_t *)(pci_dev->wmask + addr) = cpu_to_le32(wmask);
371 389 }
372 390  
373 391 static void pci_update_mappings(PCIDevice *d)
... ... @@ -476,118 +494,21 @@ uint32_t pci_default_read_config(PCIDevice *d,
476 494 return val;
477 495 }
478 496  
479   -void pci_default_write_config(PCIDevice *d,
480   - uint32_t address, uint32_t val, int len)
  497 +void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
481 498 {
482   - int can_write, i;
483   - uint32_t end, addr;
484   -
485   - if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) ||
486   - (address >= 0x30 && address < 0x34))) {
487   - PCIIORegion *r;
488   - int reg;
  499 + uint8_t orig[PCI_CONFIG_SPACE_SIZE];
  500 + int i;
489 501  
490   - if ( address >= 0x30 ) {
491   - reg = PCI_ROM_SLOT;
492   - }else{
493   - reg = (address - 0x10) >> 2;
494   - }
495   - r = &d->io_regions[reg];
496   - if (r->size == 0)
497   - goto default_config;
498   - /* compute the stored value */
499   - if (reg == PCI_ROM_SLOT) {
500   - /* keep ROM enable bit */
501   - val &= (~(r->size - 1)) | 1;
502   - } else {
503   - val &= ~(r->size - 1);
504   - val |= r->type;
505   - }
506   - *(uint32_t *)(d->config + address) = cpu_to_le32(val);
507   - pci_update_mappings(d);
508   - return;
509   - }
510   - default_config:
511 502 /* not efficient, but simple */
512   - addr = address;
513   - for(i = 0; i < len; i++) {
514   - /* default read/write accesses */
515   - switch(d->config[0x0e]) {
516   - case 0x00:
517   - case 0x80:
518   - switch(addr) {
519   - case 0x00:
520   - case 0x01:
521   - case 0x02:
522   - case 0x03:
523   - case 0x06:
524   - case 0x07:
525   - case 0x08:
526   - case 0x09:
527   - case 0x0a:
528   - case 0x0b:
529   - case 0x0e:
530   - case 0x10 ... 0x27: /* base */
531   - case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
532   - case 0x30 ... 0x33: /* rom */
533   - case 0x3d:
534   - can_write = 0;
535   - break;
536   - default:
537   - can_write = 1;
538   - break;
539   - }
540   - break;
541   - default:
542   - case 0x01:
543   - switch(addr) {
544   - case 0x00:
545   - case 0x01:
546   - case 0x02:
547   - case 0x03:
548   - case 0x06:
549   - case 0x07:
550   - case 0x08:
551   - case 0x09:
552   - case 0x0a:
553   - case 0x0b:
554   - case 0x0e:
555   - case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
556   - case 0x38 ... 0x3b: /* rom */
557   - case 0x3d:
558   - can_write = 0;
559   - break;
560   - default:
561   - can_write = 1;
562   - break;
563   - }
564   - break;
565   - }
566   - if (can_write) {
567   - /* Mask out writes to reserved bits in registers */
568   - switch (addr) {
569   - case 0x05:
570   - val &= ~PCI_COMMAND_RESERVED_MASK_HI;
571   - break;
572   - case 0x06:
573   - val &= ~PCI_STATUS_RESERVED_MASK_LO;
574   - break;
575   - case 0x07:
576   - val &= ~PCI_STATUS_RESERVED_MASK_HI;
577   - break;
578   - }
579   - d->config[addr] = val;
580   - }
581   - if (++addr > 0xff)
582   - break;
583   - val >>= 8;
  503 + memcpy(orig, d->config, PCI_CONFIG_SPACE_SIZE);
  504 + for(i = 0; i < l && addr < PCI_CONFIG_SPACE_SIZE; val >>= 8, ++i, ++addr) {
  505 + uint8_t wmask = d->wmask[addr];
  506 + d->config[addr] = (d->config[addr] & ~wmask) | (val & wmask);
584 507 }
585   -
586   - end = address + len;
587   - if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) {
588   - /* if the command register is modified, we must modify the mappings */
  508 + if (memcmp(orig + PCI_BASE_ADDRESS_0, d->config + PCI_BASE_ADDRESS_0, 24)
  509 + || ((orig[PCI_COMMAND] ^ d->config[PCI_COMMAND])
  510 + & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)))
589 511 pci_update_mappings(d);
590   - }
591 512 }
592 513  
593 514 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
... ... @@ -880,16 +801,8 @@ static void pci_bridge_write_config(PCIDevice *d,
880 801 {
881 802 PCIBridge *s = (PCIBridge *)d;
882 803  
883   - if (address == 0x19 || (address == 0x18 && len > 1)) {
884   - if (address == 0x19)
885   - s->bus->bus_num = val & 0xff;
886   - else
887   - s->bus->bus_num = (val >> 8) & 0xff;
888   -#if defined(DEBUG_PCI)
889   - printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
890   -#endif
891   - }
892 804 pci_default_write_config(d, address, val, len);
  805 + s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
893 806 }
894 807  
895 808 PCIBus *pci_find_bus(int bus_num)
... ...
hw/pci.h
... ... @@ -98,16 +98,24 @@ typedef struct PCIIORegion {
98 98 #define PCI_COMMAND 0x04 /* 16 bits */
99 99 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
100 100 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
  101 +#define PCI_COMMAND_MASTER 0x4 /* Enable bus master */
101 102 #define PCI_STATUS 0x06 /* 16 bits */
102 103 #define PCI_REVISION_ID 0x08 /* 8 bits */
103 104 #define PCI_CLASS_DEVICE 0x0a /* Device class */
  105 +#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
  106 +#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
104 107 #define PCI_HEADER_TYPE 0x0e /* 8 bits */
105 108 #define PCI_HEADER_TYPE_NORMAL 0
106 109 #define PCI_HEADER_TYPE_BRIDGE 1
107 110 #define PCI_HEADER_TYPE_CARDBUS 2
108 111 #define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
  112 +#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
  113 +#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
  114 +#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
  115 +#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
109 116 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c /* 16 bits */
110 117 #define PCI_SUBSYSTEM_ID 0x2e /* 16 bits */
  118 +#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
111 119 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
112 120 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
113 121 #define PCI_MIN_GNT 0x3e /* 8 bits */
... ... @@ -137,10 +145,18 @@ typedef struct PCIIORegion {
137 145  
138 146 #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
139 147  
  148 +/* Size of the standard PCI config header */
  149 +#define PCI_CONFIG_HEADER_SIZE 0x40
  150 +/* Size of the standard PCI config space */
  151 +#define PCI_CONFIG_SPACE_SIZE 0x100
  152 +
140 153 struct PCIDevice {
141 154 DeviceState qdev;
142 155 /* PCI config space */
143   - uint8_t config[256];
  156 + uint8_t config[PCI_CONFIG_SPACE_SIZE];
  157 +
  158 + /* Used to implement R/W bytes */
  159 + uint8_t wmask[PCI_CONFIG_SPACE_SIZE];
144 160  
145 161 /* the following fields are read only */
146 162 PCIBus *bus;
... ...