1 #include "qemu/osdep.h" 2 #include "qemu/cutils.h" 3 #include "net/net.h" 4 #include "hw/qdev-properties.h" 5 #include "qapi/error.h" 6 #include "hw/pci/pci.h" 7 #include "qapi/qapi-types-block.h" 8 #include "qapi/qapi-types-machine.h" 9 #include "qapi/qapi-types-misc.h" 10 #include "qapi/qmp/qerror.h" 11 #include "qemu/ctype.h" 12 #include "qemu/error-report.h" 13 #include "qapi/qapi-types-migration.h" 14 #include "hw/block/block.h" 15 #include "net/hub.h" 16 #include "qapi/visitor.h" 17 #include "chardev/char.h" 18 #include "qemu/uuid.h" 19 #include "qemu/units.h" 20 #include "qemu/cutils.h" 21 #include "qdev-prop-internal.h" 22 23 void qdev_prop_set_after_realize(DeviceState *dev, const char *name, 24 Error **errp) 25 { 26 if (dev->id) { 27 error_setg(errp, "Attempt to set property '%s' on device '%s' " 28 "(type '%s') after it was realized", name, dev->id, 29 object_get_typename(OBJECT(dev))); 30 } else { 31 error_setg(errp, "Attempt to set property '%s' on anonymous device " 32 "(type '%s') after it was realized", name, 33 object_get_typename(OBJECT(dev))); 34 } 35 } 36 37 void qdev_prop_allow_set_link_before_realize(const Object *obj, 38 const char *name, 39 Object *val, Error **errp) 40 { 41 DeviceState *dev = DEVICE(obj); 42 43 if (dev->realized) { 44 error_setg(errp, "Attempt to set link property '%s' on device '%s' " 45 "(type '%s') after it was realized", 46 name, dev->id, object_get_typename(obj)); 47 } 48 } 49 50 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) 51 { 52 void *ptr = dev; 53 ptr += prop->offset; 54 return ptr; 55 } 56 57 void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name, 58 void *opaque, Error **errp) 59 { 60 DeviceState *dev = DEVICE(obj); 61 Property *prop = opaque; 62 int *ptr = qdev_get_prop_ptr(dev, prop); 63 64 visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); 65 } 66 67 void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name, 68 void *opaque, Error **errp) 69 { 70 DeviceState *dev = DEVICE(obj); 71 Property *prop = opaque; 72 int *ptr = qdev_get_prop_ptr(dev, prop); 73 74 if (dev->realized) { 75 qdev_prop_set_after_realize(dev, name, errp); 76 return; 77 } 78 79 visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); 80 } 81 82 void qdev_propinfo_set_default_value_enum(ObjectProperty *op, 83 const Property *prop) 84 { 85 object_property_set_default_str(op, 86 qapi_enum_lookup(prop->info->enum_table, prop->defval.i)); 87 } 88 89 const PropertyInfo qdev_prop_enum = { 90 .name = "enum", 91 .get = qdev_propinfo_get_enum, 92 .set = qdev_propinfo_set_enum, 93 .set_default_value = qdev_propinfo_set_default_value_enum, 94 }; 95 96 /* Bit */ 97 98 static uint32_t qdev_get_prop_mask(Property *prop) 99 { 100 assert(prop->info == &qdev_prop_bit); 101 return 0x1 << prop->bitnr; 102 } 103 104 static void bit_prop_set(DeviceState *dev, Property *props, bool val) 105 { 106 uint32_t *p = qdev_get_prop_ptr(dev, props); 107 uint32_t mask = qdev_get_prop_mask(props); 108 if (val) { 109 *p |= mask; 110 } else { 111 *p &= ~mask; 112 } 113 } 114 115 static void prop_get_bit(Object *obj, Visitor *v, const char *name, 116 void *opaque, Error **errp) 117 { 118 DeviceState *dev = DEVICE(obj); 119 Property *prop = opaque; 120 uint32_t *p = qdev_get_prop_ptr(dev, prop); 121 bool value = (*p & qdev_get_prop_mask(prop)) != 0; 122 123 visit_type_bool(v, name, &value, errp); 124 } 125 126 static void prop_set_bit(Object *obj, Visitor *v, const char *name, 127 void *opaque, Error **errp) 128 { 129 DeviceState *dev = DEVICE(obj); 130 Property *prop = opaque; 131 bool value; 132 133 if (dev->realized) { 134 qdev_prop_set_after_realize(dev, name, errp); 135 return; 136 } 137 138 if (!visit_type_bool(v, name, &value, errp)) { 139 return; 140 } 141 bit_prop_set(dev, prop, value); 142 } 143 144 static void set_default_value_bool(ObjectProperty *op, const Property *prop) 145 { 146 object_property_set_default_bool(op, prop->defval.u); 147 } 148 149 const PropertyInfo qdev_prop_bit = { 150 .name = "bool", 151 .description = "on/off", 152 .get = prop_get_bit, 153 .set = prop_set_bit, 154 .set_default_value = set_default_value_bool, 155 }; 156 157 /* Bit64 */ 158 159 static uint64_t qdev_get_prop_mask64(Property *prop) 160 { 161 assert(prop->info == &qdev_prop_bit64); 162 return 0x1ull << prop->bitnr; 163 } 164 165 static void bit64_prop_set(DeviceState *dev, Property *props, bool val) 166 { 167 uint64_t *p = qdev_get_prop_ptr(dev, props); 168 uint64_t mask = qdev_get_prop_mask64(props); 169 if (val) { 170 *p |= mask; 171 } else { 172 *p &= ~mask; 173 } 174 } 175 176 static void prop_get_bit64(Object *obj, Visitor *v, const char *name, 177 void *opaque, Error **errp) 178 { 179 DeviceState *dev = DEVICE(obj); 180 Property *prop = opaque; 181 uint64_t *p = qdev_get_prop_ptr(dev, prop); 182 bool value = (*p & qdev_get_prop_mask64(prop)) != 0; 183 184 visit_type_bool(v, name, &value, errp); 185 } 186 187 static void prop_set_bit64(Object *obj, Visitor *v, const char *name, 188 void *opaque, Error **errp) 189 { 190 DeviceState *dev = DEVICE(obj); 191 Property *prop = opaque; 192 bool value; 193 194 if (dev->realized) { 195 qdev_prop_set_after_realize(dev, name, errp); 196 return; 197 } 198 199 if (!visit_type_bool(v, name, &value, errp)) { 200 return; 201 } 202 bit64_prop_set(dev, prop, value); 203 } 204 205 const PropertyInfo qdev_prop_bit64 = { 206 .name = "bool", 207 .description = "on/off", 208 .get = prop_get_bit64, 209 .set = prop_set_bit64, 210 .set_default_value = set_default_value_bool, 211 }; 212 213 /* --- bool --- */ 214 215 static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque, 216 Error **errp) 217 { 218 DeviceState *dev = DEVICE(obj); 219 Property *prop = opaque; 220 bool *ptr = qdev_get_prop_ptr(dev, prop); 221 222 visit_type_bool(v, name, ptr, errp); 223 } 224 225 static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque, 226 Error **errp) 227 { 228 DeviceState *dev = DEVICE(obj); 229 Property *prop = opaque; 230 bool *ptr = qdev_get_prop_ptr(dev, prop); 231 232 if (dev->realized) { 233 qdev_prop_set_after_realize(dev, name, errp); 234 return; 235 } 236 237 visit_type_bool(v, name, ptr, errp); 238 } 239 240 const PropertyInfo qdev_prop_bool = { 241 .name = "bool", 242 .get = get_bool, 243 .set = set_bool, 244 .set_default_value = set_default_value_bool, 245 }; 246 247 /* --- 8bit integer --- */ 248 249 static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque, 250 Error **errp) 251 { 252 DeviceState *dev = DEVICE(obj); 253 Property *prop = opaque; 254 uint8_t *ptr = qdev_get_prop_ptr(dev, prop); 255 256 visit_type_uint8(v, name, ptr, errp); 257 } 258 259 static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque, 260 Error **errp) 261 { 262 DeviceState *dev = DEVICE(obj); 263 Property *prop = opaque; 264 uint8_t *ptr = qdev_get_prop_ptr(dev, prop); 265 266 if (dev->realized) { 267 qdev_prop_set_after_realize(dev, name, errp); 268 return; 269 } 270 271 visit_type_uint8(v, name, ptr, errp); 272 } 273 274 void qdev_propinfo_set_default_value_int(ObjectProperty *op, 275 const Property *prop) 276 { 277 object_property_set_default_int(op, prop->defval.i); 278 } 279 280 void qdev_propinfo_set_default_value_uint(ObjectProperty *op, 281 const Property *prop) 282 { 283 object_property_set_default_uint(op, prop->defval.u); 284 } 285 286 const PropertyInfo qdev_prop_uint8 = { 287 .name = "uint8", 288 .get = get_uint8, 289 .set = set_uint8, 290 .set_default_value = qdev_propinfo_set_default_value_uint, 291 }; 292 293 /* --- 16bit integer --- */ 294 295 void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name, 296 void *opaque, Error **errp) 297 { 298 DeviceState *dev = DEVICE(obj); 299 Property *prop = opaque; 300 uint16_t *ptr = qdev_get_prop_ptr(dev, prop); 301 302 visit_type_uint16(v, name, ptr, errp); 303 } 304 305 static void set_uint16(Object *obj, Visitor *v, const char *name, 306 void *opaque, Error **errp) 307 { 308 DeviceState *dev = DEVICE(obj); 309 Property *prop = opaque; 310 uint16_t *ptr = qdev_get_prop_ptr(dev, prop); 311 312 if (dev->realized) { 313 qdev_prop_set_after_realize(dev, name, errp); 314 return; 315 } 316 317 visit_type_uint16(v, name, ptr, errp); 318 } 319 320 const PropertyInfo qdev_prop_uint16 = { 321 .name = "uint16", 322 .get = qdev_propinfo_get_uint16, 323 .set = set_uint16, 324 .set_default_value = qdev_propinfo_set_default_value_uint, 325 }; 326 327 /* --- 32bit integer --- */ 328 329 static void get_uint32(Object *obj, Visitor *v, const char *name, 330 void *opaque, Error **errp) 331 { 332 DeviceState *dev = DEVICE(obj); 333 Property *prop = opaque; 334 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 335 336 visit_type_uint32(v, name, ptr, errp); 337 } 338 339 static void set_uint32(Object *obj, Visitor *v, const char *name, 340 void *opaque, Error **errp) 341 { 342 DeviceState *dev = DEVICE(obj); 343 Property *prop = opaque; 344 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 345 346 if (dev->realized) { 347 qdev_prop_set_after_realize(dev, name, errp); 348 return; 349 } 350 351 visit_type_uint32(v, name, ptr, errp); 352 } 353 354 void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name, 355 void *opaque, Error **errp) 356 { 357 DeviceState *dev = DEVICE(obj); 358 Property *prop = opaque; 359 int32_t *ptr = qdev_get_prop_ptr(dev, prop); 360 361 visit_type_int32(v, name, ptr, errp); 362 } 363 364 static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque, 365 Error **errp) 366 { 367 DeviceState *dev = DEVICE(obj); 368 Property *prop = opaque; 369 int32_t *ptr = qdev_get_prop_ptr(dev, prop); 370 371 if (dev->realized) { 372 qdev_prop_set_after_realize(dev, name, errp); 373 return; 374 } 375 376 visit_type_int32(v, name, ptr, errp); 377 } 378 379 const PropertyInfo qdev_prop_uint32 = { 380 .name = "uint32", 381 .get = get_uint32, 382 .set = set_uint32, 383 .set_default_value = qdev_propinfo_set_default_value_uint, 384 }; 385 386 const PropertyInfo qdev_prop_int32 = { 387 .name = "int32", 388 .get = qdev_propinfo_get_int32, 389 .set = set_int32, 390 .set_default_value = qdev_propinfo_set_default_value_int, 391 }; 392 393 /* --- 64bit integer --- */ 394 395 static void get_uint64(Object *obj, Visitor *v, const char *name, 396 void *opaque, Error **errp) 397 { 398 DeviceState *dev = DEVICE(obj); 399 Property *prop = opaque; 400 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 401 402 visit_type_uint64(v, name, ptr, errp); 403 } 404 405 static void set_uint64(Object *obj, Visitor *v, const char *name, 406 void *opaque, Error **errp) 407 { 408 DeviceState *dev = DEVICE(obj); 409 Property *prop = opaque; 410 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 411 412 if (dev->realized) { 413 qdev_prop_set_after_realize(dev, name, errp); 414 return; 415 } 416 417 visit_type_uint64(v, name, ptr, errp); 418 } 419 420 static void get_int64(Object *obj, Visitor *v, const char *name, 421 void *opaque, Error **errp) 422 { 423 DeviceState *dev = DEVICE(obj); 424 Property *prop = opaque; 425 int64_t *ptr = qdev_get_prop_ptr(dev, prop); 426 427 visit_type_int64(v, name, ptr, errp); 428 } 429 430 static void set_int64(Object *obj, Visitor *v, const char *name, 431 void *opaque, Error **errp) 432 { 433 DeviceState *dev = DEVICE(obj); 434 Property *prop = opaque; 435 int64_t *ptr = qdev_get_prop_ptr(dev, prop); 436 437 if (dev->realized) { 438 qdev_prop_set_after_realize(dev, name, errp); 439 return; 440 } 441 442 visit_type_int64(v, name, ptr, errp); 443 } 444 445 const PropertyInfo qdev_prop_uint64 = { 446 .name = "uint64", 447 .get = get_uint64, 448 .set = set_uint64, 449 .set_default_value = qdev_propinfo_set_default_value_uint, 450 }; 451 452 const PropertyInfo qdev_prop_int64 = { 453 .name = "int64", 454 .get = get_int64, 455 .set = set_int64, 456 .set_default_value = qdev_propinfo_set_default_value_int, 457 }; 458 459 /* --- string --- */ 460 461 static void release_string(Object *obj, const char *name, void *opaque) 462 { 463 Property *prop = opaque; 464 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop)); 465 } 466 467 static void get_string(Object *obj, Visitor *v, const char *name, 468 void *opaque, Error **errp) 469 { 470 DeviceState *dev = DEVICE(obj); 471 Property *prop = opaque; 472 char **ptr = qdev_get_prop_ptr(dev, prop); 473 474 if (!*ptr) { 475 char *str = (char *)""; 476 visit_type_str(v, name, &str, errp); 477 } else { 478 visit_type_str(v, name, ptr, errp); 479 } 480 } 481 482 static void set_string(Object *obj, Visitor *v, const char *name, 483 void *opaque, Error **errp) 484 { 485 DeviceState *dev = DEVICE(obj); 486 Property *prop = opaque; 487 char **ptr = qdev_get_prop_ptr(dev, prop); 488 char *str; 489 490 if (dev->realized) { 491 qdev_prop_set_after_realize(dev, name, errp); 492 return; 493 } 494 495 if (!visit_type_str(v, name, &str, errp)) { 496 return; 497 } 498 g_free(*ptr); 499 *ptr = str; 500 } 501 502 const PropertyInfo qdev_prop_string = { 503 .name = "str", 504 .release = release_string, 505 .get = get_string, 506 .set = set_string, 507 }; 508 509 /* --- mac address --- */ 510 511 /* 512 * accepted syntax versions: 513 * 01:02:03:04:05:06 514 * 01-02-03-04-05-06 515 */ 516 static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque, 517 Error **errp) 518 { 519 DeviceState *dev = DEVICE(obj); 520 Property *prop = opaque; 521 MACAddr *mac = qdev_get_prop_ptr(dev, prop); 522 char buffer[2 * 6 + 5 + 1]; 523 char *p = buffer; 524 525 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x", 526 mac->a[0], mac->a[1], mac->a[2], 527 mac->a[3], mac->a[4], mac->a[5]); 528 529 visit_type_str(v, name, &p, errp); 530 } 531 532 static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque, 533 Error **errp) 534 { 535 DeviceState *dev = DEVICE(obj); 536 Property *prop = opaque; 537 MACAddr *mac = qdev_get_prop_ptr(dev, prop); 538 int i, pos; 539 char *str; 540 const char *p; 541 542 if (dev->realized) { 543 qdev_prop_set_after_realize(dev, name, errp); 544 return; 545 } 546 547 if (!visit_type_str(v, name, &str, errp)) { 548 return; 549 } 550 551 for (i = 0, pos = 0; i < 6; i++, pos += 3) { 552 long val; 553 554 if (!qemu_isxdigit(str[pos])) { 555 goto inval; 556 } 557 if (!qemu_isxdigit(str[pos + 1])) { 558 goto inval; 559 } 560 if (i == 5) { 561 if (str[pos + 2] != '\0') { 562 goto inval; 563 } 564 } else { 565 if (str[pos + 2] != ':' && str[pos + 2] != '-') { 566 goto inval; 567 } 568 } 569 if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) { 570 goto inval; 571 } 572 mac->a[i] = val; 573 } 574 g_free(str); 575 return; 576 577 inval: 578 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 579 g_free(str); 580 } 581 582 const PropertyInfo qdev_prop_macaddr = { 583 .name = "str", 584 .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56", 585 .get = get_mac, 586 .set = set_mac, 587 }; 588 589 /* --- Reserved Region --- */ 590 591 /* 592 * Accepted syntax: 593 * <low address>:<high address>:<type> 594 * where low/high addresses are uint64_t in hexadecimal 595 * and type is a non-negative decimal integer 596 */ 597 static void get_reserved_region(Object *obj, Visitor *v, const char *name, 598 void *opaque, Error **errp) 599 { 600 DeviceState *dev = DEVICE(obj); 601 Property *prop = opaque; 602 ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); 603 char buffer[64]; 604 char *p = buffer; 605 int rc; 606 607 rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u", 608 rr->low, rr->high, rr->type); 609 assert(rc < sizeof(buffer)); 610 611 visit_type_str(v, name, &p, errp); 612 } 613 614 static void set_reserved_region(Object *obj, Visitor *v, const char *name, 615 void *opaque, Error **errp) 616 { 617 DeviceState *dev = DEVICE(obj); 618 Property *prop = opaque; 619 ReservedRegion *rr = qdev_get_prop_ptr(dev, prop); 620 Error *local_err = NULL; 621 const char *endptr; 622 char *str; 623 int ret; 624 625 if (dev->realized) { 626 qdev_prop_set_after_realize(dev, name, errp); 627 return; 628 } 629 630 visit_type_str(v, name, &str, &local_err); 631 if (local_err) { 632 error_propagate(errp, local_err); 633 return; 634 } 635 636 ret = qemu_strtou64(str, &endptr, 16, &rr->low); 637 if (ret) { 638 error_setg(errp, "start address of '%s'" 639 " must be a hexadecimal integer", name); 640 goto out; 641 } 642 if (*endptr != ':') { 643 goto separator_error; 644 } 645 646 ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high); 647 if (ret) { 648 error_setg(errp, "end address of '%s'" 649 " must be a hexadecimal integer", name); 650 goto out; 651 } 652 if (*endptr != ':') { 653 goto separator_error; 654 } 655 656 ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type); 657 if (ret) { 658 error_setg(errp, "type of '%s'" 659 " must be a non-negative decimal integer", name); 660 } 661 goto out; 662 663 separator_error: 664 error_setg(errp, "reserved region fields must be separated with ':'"); 665 out: 666 g_free(str); 667 return; 668 } 669 670 const PropertyInfo qdev_prop_reserved_region = { 671 .name = "reserved_region", 672 .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0", 673 .get = get_reserved_region, 674 .set = set_reserved_region, 675 }; 676 677 /* --- on/off/auto --- */ 678 679 const PropertyInfo qdev_prop_on_off_auto = { 680 .name = "OnOffAuto", 681 .description = "on/off/auto", 682 .enum_table = &OnOffAuto_lookup, 683 .get = qdev_propinfo_get_enum, 684 .set = qdev_propinfo_set_enum, 685 .set_default_value = qdev_propinfo_set_default_value_enum, 686 }; 687 688 /* --- lost tick policy --- */ 689 690 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int)); 691 692 const PropertyInfo qdev_prop_losttickpolicy = { 693 .name = "LostTickPolicy", 694 .enum_table = &LostTickPolicy_lookup, 695 .get = qdev_propinfo_get_enum, 696 .set = qdev_propinfo_set_enum, 697 .set_default_value = qdev_propinfo_set_default_value_enum, 698 }; 699 700 /* --- Block device error handling policy --- */ 701 702 QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int)); 703 704 const PropertyInfo qdev_prop_blockdev_on_error = { 705 .name = "BlockdevOnError", 706 .description = "Error handling policy, " 707 "report/ignore/enospc/stop/auto", 708 .enum_table = &BlockdevOnError_lookup, 709 .get = qdev_propinfo_get_enum, 710 .set = qdev_propinfo_set_enum, 711 .set_default_value = qdev_propinfo_set_default_value_enum, 712 }; 713 714 /* --- BIOS CHS translation */ 715 716 QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); 717 718 const PropertyInfo qdev_prop_bios_chs_trans = { 719 .name = "BiosAtaTranslation", 720 .description = "Logical CHS translation algorithm, " 721 "auto/none/lba/large/rechs", 722 .enum_table = &BiosAtaTranslation_lookup, 723 .get = qdev_propinfo_get_enum, 724 .set = qdev_propinfo_set_enum, 725 .set_default_value = qdev_propinfo_set_default_value_enum, 726 }; 727 728 /* --- FDC default drive types */ 729 730 const PropertyInfo qdev_prop_fdc_drive_type = { 731 .name = "FdcDriveType", 732 .description = "FDC drive type, " 733 "144/288/120/none/auto", 734 .enum_table = &FloppyDriveType_lookup, 735 .get = qdev_propinfo_get_enum, 736 .set = qdev_propinfo_set_enum, 737 .set_default_value = qdev_propinfo_set_default_value_enum, 738 }; 739 740 /* --- MultiFDCompression --- */ 741 742 const PropertyInfo qdev_prop_multifd_compression = { 743 .name = "MultiFDCompression", 744 .description = "multifd_compression values, " 745 "none/zlib/zstd", 746 .enum_table = &MultiFDCompression_lookup, 747 .get = qdev_propinfo_get_enum, 748 .set = qdev_propinfo_set_enum, 749 .set_default_value = qdev_propinfo_set_default_value_enum, 750 }; 751 752 /* --- pci address --- */ 753 754 /* 755 * bus-local address, i.e. "$slot" or "$slot.$fn" 756 */ 757 static void set_pci_devfn(Object *obj, Visitor *v, const char *name, 758 void *opaque, Error **errp) 759 { 760 DeviceState *dev = DEVICE(obj); 761 Property *prop = opaque; 762 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop); 763 unsigned int slot, fn, n; 764 char *str; 765 766 if (dev->realized) { 767 qdev_prop_set_after_realize(dev, name, errp); 768 return; 769 } 770 771 if (!visit_type_str(v, name, &str, NULL)) { 772 if (!visit_type_int32(v, name, &value, errp)) { 773 return; 774 } 775 if (value < -1 || value > 255) { 776 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 777 name ? name : "null", "pci_devfn"); 778 return; 779 } 780 *ptr = value; 781 return; 782 } 783 784 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { 785 fn = 0; 786 if (sscanf(str, "%x%n", &slot, &n) != 1) { 787 goto invalid; 788 } 789 } 790 if (str[n] != '\0' || fn > 7 || slot > 31) { 791 goto invalid; 792 } 793 *ptr = slot << 3 | fn; 794 g_free(str); 795 return; 796 797 invalid: 798 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 799 g_free(str); 800 } 801 802 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, 803 size_t len) 804 { 805 int32_t *ptr = qdev_get_prop_ptr(dev, prop); 806 807 if (*ptr == -1) { 808 return snprintf(dest, len, "<unset>"); 809 } else { 810 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); 811 } 812 } 813 814 const PropertyInfo qdev_prop_pci_devfn = { 815 .name = "int32", 816 .description = "Slot and optional function number, example: 06.0 or 06", 817 .print = print_pci_devfn, 818 .get = get_int32, 819 .set = set_pci_devfn, 820 .set_default_value = set_default_value_int, 821 }; 822 823 /* --- 32bit unsigned int 'size' type --- */ 824 825 void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, 826 void *opaque, Error **errp) 827 { 828 DeviceState *dev = DEVICE(obj); 829 Property *prop = opaque; 830 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 831 uint64_t value = *ptr; 832 833 visit_type_size(v, name, &value, errp); 834 } 835 836 static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque, 837 Error **errp) 838 { 839 DeviceState *dev = DEVICE(obj); 840 Property *prop = opaque; 841 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 842 uint64_t value; 843 844 if (dev->realized) { 845 qdev_prop_set_after_realize(dev, name, errp); 846 return; 847 } 848 849 if (!visit_type_size(v, name, &value, errp)) { 850 return; 851 } 852 853 if (value > UINT32_MAX) { 854 error_setg(errp, 855 "Property %s.%s doesn't take value %" PRIu64 856 " (maximum: %u)", 857 dev->id ? : "", name, value, UINT32_MAX); 858 return; 859 } 860 861 *ptr = value; 862 } 863 864 const PropertyInfo qdev_prop_size32 = { 865 .name = "size", 866 .get = qdev_propinfo_get_size32, 867 .set = set_size32, 868 .set_default_value = qdev_propinfo_set_default_value_uint, 869 }; 870 871 /* --- blocksize --- */ 872 873 /* lower limit is sector size */ 874 #define MIN_BLOCK_SIZE 512 875 #define MIN_BLOCK_SIZE_STR "512 B" 876 /* 877 * upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and 878 * matches qcow2 cluster size limit 879 */ 880 #define MAX_BLOCK_SIZE (2 * MiB) 881 #define MAX_BLOCK_SIZE_STR "2 MiB" 882 883 static void set_blocksize(Object *obj, Visitor *v, const char *name, 884 void *opaque, Error **errp) 885 { 886 DeviceState *dev = DEVICE(obj); 887 Property *prop = opaque; 888 uint32_t *ptr = qdev_get_prop_ptr(dev, prop); 889 uint64_t value; 890 891 if (dev->realized) { 892 qdev_prop_set_after_realize(dev, name, errp); 893 return; 894 } 895 896 if (!visit_type_size(v, name, &value, errp)) { 897 return; 898 } 899 /* value of 0 means "unset" */ 900 if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) { 901 error_setg(errp, 902 "Property %s.%s doesn't take value %" PRIu64 903 " (minimum: " MIN_BLOCK_SIZE_STR 904 ", maximum: " MAX_BLOCK_SIZE_STR ")", 905 dev->id ? : "", name, value); 906 return; 907 } 908 909 /* We rely on power-of-2 blocksizes for bitmasks */ 910 if ((value & (value - 1)) != 0) { 911 error_setg(errp, 912 "Property %s.%s doesn't take value '%" PRId64 "', " 913 "it's not a power of 2", dev->id ?: "", name, (int64_t)value); 914 return; 915 } 916 917 *ptr = value; 918 } 919 920 const PropertyInfo qdev_prop_blocksize = { 921 .name = "size", 922 .description = "A power of two between " MIN_BLOCK_SIZE_STR 923 " and " MAX_BLOCK_SIZE_STR, 924 .get = qdev_propinfo_get_size32, 925 .set = set_blocksize, 926 .set_default_value = qdev_propinfo_set_default_value_uint, 927 }; 928 929 /* --- pci host address --- */ 930 931 static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name, 932 void *opaque, Error **errp) 933 { 934 DeviceState *dev = DEVICE(obj); 935 Property *prop = opaque; 936 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); 937 char buffer[] = "ffff:ff:ff.f"; 938 char *p = buffer; 939 int rc = 0; 940 941 /* 942 * Catch "invalid" device reference from vfio-pci and allow the 943 * default buffer representing the non-existent device to be used. 944 */ 945 if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) { 946 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d", 947 addr->domain, addr->bus, addr->slot, addr->function); 948 assert(rc == sizeof(buffer) - 1); 949 } 950 951 visit_type_str(v, name, &p, errp); 952 } 953 954 /* 955 * Parse [<domain>:]<bus>:<slot>.<func> 956 * if <domain> is not supplied, it's assumed to be 0. 957 */ 958 static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name, 959 void *opaque, Error **errp) 960 { 961 DeviceState *dev = DEVICE(obj); 962 Property *prop = opaque; 963 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); 964 char *str, *p; 965 const char *e; 966 unsigned long val; 967 unsigned long dom = 0, bus = 0; 968 unsigned int slot = 0, func = 0; 969 970 if (dev->realized) { 971 qdev_prop_set_after_realize(dev, name, errp); 972 return; 973 } 974 975 if (!visit_type_str(v, name, &str, errp)) { 976 return; 977 } 978 979 p = str; 980 if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0xffff || e == p) { 981 goto inval; 982 } 983 if (*e != ':') { 984 goto inval; 985 } 986 bus = val; 987 988 p = (char *)e + 1; 989 if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) { 990 goto inval; 991 } 992 if (*e == ':') { 993 dom = bus; 994 bus = val; 995 p = (char *)e + 1; 996 if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) { 997 goto inval; 998 } 999 } 1000 slot = val; 1001 1002 if (*e != '.') { 1003 goto inval; 1004 } 1005 p = (char *)e + 1; 1006 if (qemu_strtoul(p, &e, 10, &val) < 0 || val > 7 || e == p) { 1007 goto inval; 1008 } 1009 func = val; 1010 1011 if (bus > 0xff) { 1012 goto inval; 1013 } 1014 1015 if (*e) { 1016 goto inval; 1017 } 1018 1019 addr->domain = dom; 1020 addr->bus = bus; 1021 addr->slot = slot; 1022 addr->function = func; 1023 1024 g_free(str); 1025 return; 1026 1027 inval: 1028 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 1029 g_free(str); 1030 } 1031 1032 const PropertyInfo qdev_prop_pci_host_devaddr = { 1033 .name = "str", 1034 .description = "Address (bus/device/function) of " 1035 "the host device, example: 04:10.0", 1036 .get = get_pci_host_devaddr, 1037 .set = set_pci_host_devaddr, 1038 }; 1039 1040 /* --- UUID --- */ 1041 1042 static void get_uuid(Object *obj, Visitor *v, const char *name, void *opaque, 1043 Error **errp) 1044 { 1045 DeviceState *dev = DEVICE(obj); 1046 Property *prop = opaque; 1047 QemuUUID *uuid = qdev_get_prop_ptr(dev, prop); 1048 char buffer[UUID_FMT_LEN + 1]; 1049 char *p = buffer; 1050 1051 qemu_uuid_unparse(uuid, buffer); 1052 1053 visit_type_str(v, name, &p, errp); 1054 } 1055 1056 #define UUID_VALUE_AUTO "auto" 1057 1058 static void set_uuid(Object *obj, Visitor *v, const char *name, void *opaque, 1059 Error **errp) 1060 { 1061 DeviceState *dev = DEVICE(obj); 1062 Property *prop = opaque; 1063 QemuUUID *uuid = qdev_get_prop_ptr(dev, prop); 1064 char *str; 1065 1066 if (dev->realized) { 1067 qdev_prop_set_after_realize(dev, name, errp); 1068 return; 1069 } 1070 1071 if (!visit_type_str(v, name, &str, errp)) { 1072 return; 1073 } 1074 1075 if (!strcmp(str, UUID_VALUE_AUTO)) { 1076 qemu_uuid_generate(uuid); 1077 } else if (qemu_uuid_parse(str, uuid) < 0) { 1078 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str); 1079 } 1080 g_free(str); 1081 } 1082 1083 static void set_default_uuid_auto(ObjectProperty *op, const Property *prop) 1084 { 1085 object_property_set_default_str(op, UUID_VALUE_AUTO); 1086 } 1087 1088 const PropertyInfo qdev_prop_uuid = { 1089 .name = "str", 1090 .description = "UUID (aka GUID) or \"" UUID_VALUE_AUTO 1091 "\" for random value (default)", 1092 .get = get_uuid, 1093 .set = set_uuid, 1094 .set_default_value = set_default_uuid_auto, 1095 }; 1096 1097 /* --- support for array properties --- */ 1098 1099 /* Used as an opaque for the object properties we add for each 1100 * array element. Note that the struct Property must be first 1101 * in the struct so that a pointer to this works as the opaque 1102 * for the underlying element's property hooks as well as for 1103 * our own release callback. 1104 */ 1105 typedef struct { 1106 struct Property prop; 1107 char *propname; 1108 ObjectPropertyRelease *release; 1109 } ArrayElementProperty; 1110 1111 /* object property release callback for array element properties: 1112 * we call the underlying element's property release hook, and 1113 * then free the memory we allocated when we added the property. 1114 */ 1115 static void array_element_release(Object *obj, const char *name, void *opaque) 1116 { 1117 ArrayElementProperty *p = opaque; 1118 if (p->release) { 1119 p->release(obj, name, opaque); 1120 } 1121 g_free(p->propname); 1122 g_free(p); 1123 } 1124 1125 static void set_prop_arraylen(Object *obj, Visitor *v, const char *name, 1126 void *opaque, Error **errp) 1127 { 1128 /* Setter for the property which defines the length of a 1129 * variable-sized property array. As well as actually setting the 1130 * array-length field in the device struct, we have to create the 1131 * array itself and dynamically add the corresponding properties. 1132 */ 1133 DeviceState *dev = DEVICE(obj); 1134 Property *prop = opaque; 1135 uint32_t *alenptr = qdev_get_prop_ptr(dev, prop); 1136 void **arrayptr = (void *)dev + prop->arrayoffset; 1137 void *eltptr; 1138 const char *arrayname; 1139 int i; 1140 1141 if (dev->realized) { 1142 qdev_prop_set_after_realize(dev, name, errp); 1143 return; 1144 } 1145 if (*alenptr) { 1146 error_setg(errp, "array size property %s may not be set more than once", 1147 name); 1148 return; 1149 } 1150 if (!visit_type_uint32(v, name, alenptr, errp)) { 1151 return; 1152 } 1153 if (!*alenptr) { 1154 return; 1155 } 1156 1157 /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix; 1158 * strip it off so we can get the name of the array itself. 1159 */ 1160 assert(strncmp(name, PROP_ARRAY_LEN_PREFIX, 1161 strlen(PROP_ARRAY_LEN_PREFIX)) == 0); 1162 arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX); 1163 1164 /* Note that it is the responsibility of the individual device's deinit 1165 * to free the array proper. 1166 */ 1167 *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize); 1168 for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) { 1169 char *propname = g_strdup_printf("%s[%d]", arrayname, i); 1170 ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1); 1171 arrayprop->release = prop->arrayinfo->release; 1172 arrayprop->propname = propname; 1173 arrayprop->prop.info = prop->arrayinfo; 1174 arrayprop->prop.name = propname; 1175 /* This ugly piece of pointer arithmetic sets up the offset so 1176 * that when the underlying get/set hooks call qdev_get_prop_ptr 1177 * they get the right answer despite the array element not actually 1178 * being inside the device struct. 1179 */ 1180 arrayprop->prop.offset = eltptr - (void *)dev; 1181 assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr); 1182 object_property_add(obj, propname, 1183 arrayprop->prop.info->name, 1184 arrayprop->prop.info->get, 1185 arrayprop->prop.info->set, 1186 array_element_release, 1187 arrayprop); 1188 } 1189 } 1190 1191 const PropertyInfo qdev_prop_arraylen = { 1192 .name = "uint32", 1193 .get = get_uint32, 1194 .set = set_prop_arraylen, 1195 .set_default_value = qdev_propinfo_set_default_value_uint, 1196 }; 1197 1198 /* --- public helpers --- */ 1199 1200 static Property *qdev_prop_walk(Property *props, const char *name) 1201 { 1202 if (!props) { 1203 return NULL; 1204 } 1205 while (props->name) { 1206 if (strcmp(props->name, name) == 0) { 1207 return props; 1208 } 1209 props++; 1210 } 1211 return NULL; 1212 } 1213 1214 static Property *qdev_prop_find(DeviceState *dev, const char *name) 1215 { 1216 ObjectClass *class; 1217 Property *prop; 1218 1219 /* device properties */ 1220 class = object_get_class(OBJECT(dev)); 1221 do { 1222 prop = qdev_prop_walk(DEVICE_CLASS(class)->props_, name); 1223 if (prop) { 1224 return prop; 1225 } 1226 class = object_class_get_parent(class); 1227 } while (class != object_class_by_name(TYPE_DEVICE)); 1228 1229 return NULL; 1230 } 1231 1232 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev, 1233 Property *prop, const char *value) 1234 { 1235 switch (ret) { 1236 case -EEXIST: 1237 error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use", 1238 object_get_typename(OBJECT(dev)), prop->name, value); 1239 break; 1240 default: 1241 case -EINVAL: 1242 error_setg(errp, QERR_PROPERTY_VALUE_BAD, 1243 object_get_typename(OBJECT(dev)), prop->name, value); 1244 break; 1245 case -ENOENT: 1246 error_setg(errp, "Property '%s.%s' can't find value '%s'", 1247 object_get_typename(OBJECT(dev)), prop->name, value); 1248 break; 1249 case 0: 1250 break; 1251 } 1252 } 1253 1254 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value) 1255 { 1256 object_property_set_bool(OBJECT(dev), name, value, &error_abort); 1257 } 1258 1259 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) 1260 { 1261 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1262 } 1263 1264 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) 1265 { 1266 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1267 } 1268 1269 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) 1270 { 1271 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1272 } 1273 1274 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) 1275 { 1276 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1277 } 1278 1279 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) 1280 { 1281 object_property_set_int(OBJECT(dev), name, value, &error_abort); 1282 } 1283 1284 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value) 1285 { 1286 object_property_set_str(OBJECT(dev), name, value, &error_abort); 1287 } 1288 1289 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, 1290 const uint8_t *value) 1291 { 1292 char str[2 * 6 + 5 + 1]; 1293 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", 1294 value[0], value[1], value[2], value[3], value[4], value[5]); 1295 1296 object_property_set_str(OBJECT(dev), name, str, &error_abort); 1297 } 1298 1299 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) 1300 { 1301 Property *prop; 1302 1303 prop = qdev_prop_find(dev, name); 1304 object_property_set_str(OBJECT(dev), name, 1305 qapi_enum_lookup(prop->info->enum_table, value), 1306 &error_abort); 1307 } 1308 1309 static GPtrArray *global_props(void) 1310 { 1311 static GPtrArray *gp; 1312 1313 if (!gp) { 1314 gp = g_ptr_array_new(); 1315 } 1316 1317 return gp; 1318 } 1319 1320 void qdev_prop_register_global(GlobalProperty *prop) 1321 { 1322 g_ptr_array_add(global_props(), prop); 1323 } 1324 1325 const GlobalProperty *qdev_find_global_prop(DeviceState *dev, 1326 const char *name) 1327 { 1328 GPtrArray *props = global_props(); 1329 const GlobalProperty *p; 1330 int i; 1331 1332 for (i = 0; i < props->len; i++) { 1333 p = g_ptr_array_index(props, i); 1334 if (object_dynamic_cast(OBJECT(dev), p->driver) 1335 && !strcmp(p->property, name)) { 1336 return p; 1337 } 1338 } 1339 return NULL; 1340 } 1341 1342 int qdev_prop_check_globals(void) 1343 { 1344 int i, ret = 0; 1345 1346 for (i = 0; i < global_props()->len; i++) { 1347 GlobalProperty *prop; 1348 ObjectClass *oc; 1349 DeviceClass *dc; 1350 1351 prop = g_ptr_array_index(global_props(), i); 1352 if (prop->used) { 1353 continue; 1354 } 1355 oc = object_class_by_name(prop->driver); 1356 oc = object_class_dynamic_cast(oc, TYPE_DEVICE); 1357 if (!oc) { 1358 warn_report("global %s.%s has invalid class name", 1359 prop->driver, prop->property); 1360 ret = 1; 1361 continue; 1362 } 1363 dc = DEVICE_CLASS(oc); 1364 if (!dc->hotpluggable && !prop->used) { 1365 warn_report("global %s.%s=%s not used", 1366 prop->driver, prop->property, prop->value); 1367 ret = 1; 1368 continue; 1369 } 1370 } 1371 return ret; 1372 } 1373 1374 void qdev_prop_set_globals(DeviceState *dev) 1375 { 1376 object_apply_global_props(OBJECT(dev), global_props(), 1377 dev->hotplugged ? NULL : &error_fatal); 1378 } 1379 1380 /* --- 64bit unsigned int 'size' type --- */ 1381 1382 static void get_size(Object *obj, Visitor *v, const char *name, void *opaque, 1383 Error **errp) 1384 { 1385 DeviceState *dev = DEVICE(obj); 1386 Property *prop = opaque; 1387 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 1388 1389 visit_type_size(v, name, ptr, errp); 1390 } 1391 1392 static void set_size(Object *obj, Visitor *v, const char *name, void *opaque, 1393 Error **errp) 1394 { 1395 DeviceState *dev = DEVICE(obj); 1396 Property *prop = opaque; 1397 uint64_t *ptr = qdev_get_prop_ptr(dev, prop); 1398 1399 visit_type_size(v, name, ptr, errp); 1400 } 1401 1402 const PropertyInfo qdev_prop_size = { 1403 .name = "size", 1404 .get = get_size, 1405 .set = set_size, 1406 .set_default_value = qdev_propinfo_set_default_value_uint, 1407 }; 1408 1409 /* --- object link property --- */ 1410 1411 static void create_link_property(ObjectClass *oc, Property *prop) 1412 { 1413 object_class_property_add_link(oc, prop->name, prop->link_type, 1414 prop->offset, 1415 qdev_prop_allow_set_link_before_realize, 1416 OBJ_PROP_LINK_STRONG); 1417 } 1418 1419 const PropertyInfo qdev_prop_link = { 1420 .name = "link", 1421 .create = create_link_property, 1422 }; 1423 1424 /* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */ 1425 1426 const PropertyInfo qdev_prop_off_auto_pcibar = { 1427 .name = "OffAutoPCIBAR", 1428 .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5", 1429 .enum_table = &OffAutoPCIBAR_lookup, 1430 .get = qdev_propinfo_get_enum, 1431 .set = qdev_propinfo_set_enum, 1432 .set_default_value = qdev_propinfo_set_default_value_enum, 1433 }; 1434 1435 /* --- PCIELinkSpeed 2_5/5/8/16 -- */ 1436 1437 static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, 1438 void *opaque, Error **errp) 1439 { 1440 DeviceState *dev = DEVICE(obj); 1441 Property *prop = opaque; 1442 PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); 1443 int speed; 1444 1445 switch (*p) { 1446 case QEMU_PCI_EXP_LNK_2_5GT: 1447 speed = PCIE_LINK_SPEED_2_5; 1448 break; 1449 case QEMU_PCI_EXP_LNK_5GT: 1450 speed = PCIE_LINK_SPEED_5; 1451 break; 1452 case QEMU_PCI_EXP_LNK_8GT: 1453 speed = PCIE_LINK_SPEED_8; 1454 break; 1455 case QEMU_PCI_EXP_LNK_16GT: 1456 speed = PCIE_LINK_SPEED_16; 1457 break; 1458 default: 1459 /* Unreachable */ 1460 abort(); 1461 } 1462 1463 visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp); 1464 } 1465 1466 static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name, 1467 void *opaque, Error **errp) 1468 { 1469 DeviceState *dev = DEVICE(obj); 1470 Property *prop = opaque; 1471 PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop); 1472 int speed; 1473 1474 if (dev->realized) { 1475 qdev_prop_set_after_realize(dev, name, errp); 1476 return; 1477 } 1478 1479 if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table, 1480 errp)) { 1481 return; 1482 } 1483 1484 switch (speed) { 1485 case PCIE_LINK_SPEED_2_5: 1486 *p = QEMU_PCI_EXP_LNK_2_5GT; 1487 break; 1488 case PCIE_LINK_SPEED_5: 1489 *p = QEMU_PCI_EXP_LNK_5GT; 1490 break; 1491 case PCIE_LINK_SPEED_8: 1492 *p = QEMU_PCI_EXP_LNK_8GT; 1493 break; 1494 case PCIE_LINK_SPEED_16: 1495 *p = QEMU_PCI_EXP_LNK_16GT; 1496 break; 1497 default: 1498 /* Unreachable */ 1499 abort(); 1500 } 1501 } 1502 1503 const PropertyInfo qdev_prop_pcie_link_speed = { 1504 .name = "PCIELinkSpeed", 1505 .description = "2_5/5/8/16", 1506 .enum_table = &PCIELinkSpeed_lookup, 1507 .get = get_prop_pcielinkspeed, 1508 .set = set_prop_pcielinkspeed, 1509 .set_default_value = qdev_propinfo_set_default_value_enum, 1510 }; 1511 1512 /* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */ 1513 1514 static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, 1515 void *opaque, Error **errp) 1516 { 1517 DeviceState *dev = DEVICE(obj); 1518 Property *prop = opaque; 1519 PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); 1520 int width; 1521 1522 switch (*p) { 1523 case QEMU_PCI_EXP_LNK_X1: 1524 width = PCIE_LINK_WIDTH_1; 1525 break; 1526 case QEMU_PCI_EXP_LNK_X2: 1527 width = PCIE_LINK_WIDTH_2; 1528 break; 1529 case QEMU_PCI_EXP_LNK_X4: 1530 width = PCIE_LINK_WIDTH_4; 1531 break; 1532 case QEMU_PCI_EXP_LNK_X8: 1533 width = PCIE_LINK_WIDTH_8; 1534 break; 1535 case QEMU_PCI_EXP_LNK_X12: 1536 width = PCIE_LINK_WIDTH_12; 1537 break; 1538 case QEMU_PCI_EXP_LNK_X16: 1539 width = PCIE_LINK_WIDTH_16; 1540 break; 1541 case QEMU_PCI_EXP_LNK_X32: 1542 width = PCIE_LINK_WIDTH_32; 1543 break; 1544 default: 1545 /* Unreachable */ 1546 abort(); 1547 } 1548 1549 visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp); 1550 } 1551 1552 static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name, 1553 void *opaque, Error **errp) 1554 { 1555 DeviceState *dev = DEVICE(obj); 1556 Property *prop = opaque; 1557 PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop); 1558 int width; 1559 1560 if (dev->realized) { 1561 qdev_prop_set_after_realize(dev, name, errp); 1562 return; 1563 } 1564 1565 if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table, 1566 errp)) { 1567 return; 1568 } 1569 1570 switch (width) { 1571 case PCIE_LINK_WIDTH_1: 1572 *p = QEMU_PCI_EXP_LNK_X1; 1573 break; 1574 case PCIE_LINK_WIDTH_2: 1575 *p = QEMU_PCI_EXP_LNK_X2; 1576 break; 1577 case PCIE_LINK_WIDTH_4: 1578 *p = QEMU_PCI_EXP_LNK_X4; 1579 break; 1580 case PCIE_LINK_WIDTH_8: 1581 *p = QEMU_PCI_EXP_LNK_X8; 1582 break; 1583 case PCIE_LINK_WIDTH_12: 1584 *p = QEMU_PCI_EXP_LNK_X12; 1585 break; 1586 case PCIE_LINK_WIDTH_16: 1587 *p = QEMU_PCI_EXP_LNK_X16; 1588 break; 1589 case PCIE_LINK_WIDTH_32: 1590 *p = QEMU_PCI_EXP_LNK_X32; 1591 break; 1592 default: 1593 /* Unreachable */ 1594 abort(); 1595 } 1596 } 1597 1598 const PropertyInfo qdev_prop_pcie_link_width = { 1599 .name = "PCIELinkWidth", 1600 .description = "1/2/4/8/12/16/32", 1601 .enum_table = &PCIELinkWidth_lookup, 1602 .get = get_prop_pcielinkwidth, 1603 .set = set_prop_pcielinkwidth, 1604 .set_default_value = qdev_propinfo_set_default_value_enum, 1605 }; 1606