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