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