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,6 +255,17 @@ static PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
255 return pci_find_bus(bus); 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 /* -1 for devfn means auto assign */ 269 /* -1 for devfn means auto assign */
259 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, 270 static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
260 const char *name, int devfn, 271 const char *name, int devfn,
@@ -276,6 +287,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, @@ -276,6 +287,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
276 pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); 287 pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
277 memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state)); 288 memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
278 pci_set_default_subsystem_id(pci_dev); 289 pci_set_default_subsystem_id(pci_dev);
  290 + pci_init_wmask(pci_dev);
279 291
280 if (!config_read) 292 if (!config_read)
281 config_read = pci_default_read_config; 293 config_read = pci_default_read_config;
@@ -347,6 +359,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, @@ -347,6 +359,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
347 { 359 {
348 PCIIORegion *r; 360 PCIIORegion *r;
349 uint32_t addr; 361 uint32_t addr;
  362 + uint32_t wmask;
350 363
351 if ((unsigned int)region_num >= PCI_NUM_REGIONS) 364 if ((unsigned int)region_num >= PCI_NUM_REGIONS)
352 return; 365 return;
@@ -362,12 +375,17 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, @@ -362,12 +375,17 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
362 r->size = size; 375 r->size = size;
363 r->type = type; 376 r->type = type;
364 r->map_func = map_func; 377 r->map_func = map_func;
  378 +
  379 + wmask = ~(size - 1);
365 if (region_num == PCI_ROM_SLOT) { 380 if (region_num == PCI_ROM_SLOT) {
366 addr = 0x30; 381 addr = 0x30;
  382 + /* ROM enable bit is writeable */
  383 + wmask |= 1;
367 } else { 384 } else {
368 addr = 0x10 + region_num * 4; 385 addr = 0x10 + region_num * 4;
369 } 386 }
370 *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type); 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 static void pci_update_mappings(PCIDevice *d) 391 static void pci_update_mappings(PCIDevice *d)
@@ -476,118 +494,21 @@ uint32_t pci_default_read_config(PCIDevice *d, @@ -476,118 +494,21 @@ uint32_t pci_default_read_config(PCIDevice *d,
476 return val; 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 /* not efficient, but simple */ 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 pci_update_mappings(d); 511 pci_update_mappings(d);
590 - }  
591 } 512 }
592 513
593 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len) 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,16 +801,8 @@ static void pci_bridge_write_config(PCIDevice *d,
880 { 801 {
881 PCIBridge *s = (PCIBridge *)d; 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 pci_default_write_config(d, address, val, len); 804 pci_default_write_config(d, address, val, len);
  805 + s->bus->bus_num = d->config[PCI_SECONDARY_BUS];
893 } 806 }
894 807
895 PCIBus *pci_find_bus(int bus_num) 808 PCIBus *pci_find_bus(int bus_num)
hw/pci.h
@@ -98,16 +98,24 @@ typedef struct PCIIORegion { @@ -98,16 +98,24 @@ typedef struct PCIIORegion {
98 #define PCI_COMMAND 0x04 /* 16 bits */ 98 #define PCI_COMMAND 0x04 /* 16 bits */
99 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ 99 #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
100 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ 100 #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
  101 +#define PCI_COMMAND_MASTER 0x4 /* Enable bus master */
101 #define PCI_STATUS 0x06 /* 16 bits */ 102 #define PCI_STATUS 0x06 /* 16 bits */
102 #define PCI_REVISION_ID 0x08 /* 8 bits */ 103 #define PCI_REVISION_ID 0x08 /* 8 bits */
103 #define PCI_CLASS_DEVICE 0x0a /* Device class */ 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 #define PCI_HEADER_TYPE 0x0e /* 8 bits */ 107 #define PCI_HEADER_TYPE 0x0e /* 8 bits */
105 #define PCI_HEADER_TYPE_NORMAL 0 108 #define PCI_HEADER_TYPE_NORMAL 0
106 #define PCI_HEADER_TYPE_BRIDGE 1 109 #define PCI_HEADER_TYPE_BRIDGE 1
107 #define PCI_HEADER_TYPE_CARDBUS 2 110 #define PCI_HEADER_TYPE_CARDBUS 2
108 #define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80 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 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c /* 16 bits */ 116 #define PCI_SUBSYSTEM_VENDOR_ID 0x2c /* 16 bits */
110 #define PCI_SUBSYSTEM_ID 0x2e /* 16 bits */ 117 #define PCI_SUBSYSTEM_ID 0x2e /* 16 bits */
  118 +#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
111 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ 119 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
112 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ 120 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
113 #define PCI_MIN_GNT 0x3e /* 8 bits */ 121 #define PCI_MIN_GNT 0x3e /* 8 bits */
@@ -137,10 +145,18 @@ typedef struct PCIIORegion { @@ -137,10 +145,18 @@ typedef struct PCIIORegion {
137 145
138 #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8) 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 struct PCIDevice { 153 struct PCIDevice {
141 DeviceState qdev; 154 DeviceState qdev;
142 /* PCI config space */ 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 /* the following fields are read only */ 161 /* the following fields are read only */
146 PCIBus *bus; 162 PCIBus *bus;