qdev-properties.c 33.1 KB
Newer Older
P
Peter Maydell 已提交
1
#include "qemu/osdep.h"
P
Paolo Bonzini 已提交
2
#include "net/net.h"
3
#include "hw/qdev.h"
4
#include "qapi/error.h"
5
#include "hw/pci/pci.h"
6
#include "qapi/qmp/qerror.h"
7
#include "qemu/error-report.h"
8
#include "sysemu/block-backend.h"
P
Paolo Bonzini 已提交
9
#include "hw/block/block.h"
10
#include "net/hub.h"
11
#include "qapi/visitor.h"
12
#include "chardev/char.h"
G
Gerd Hoffmann 已提交
13

14 15 16 17 18 19 20 21 22 23 24 25 26 27
void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
                                  Error **errp)
{
    if (dev->id) {
        error_setg(errp, "Attempt to set property '%s' on device '%s' "
                   "(type '%s') after it was realized", name, dev->id,
                   object_get_typename(OBJECT(dev)));
    } else {
        error_setg(errp, "Attempt to set property '%s' on anonymous device "
                   "(type '%s') after it was realized", name,
                   object_get_typename(OBJECT(dev)));
    }
}

28 29
void qdev_prop_allow_set_link_before_realize(const Object *obj,
                                             const char *name,
30 31 32 33 34 35 36 37 38 39 40
                                             Object *val, Error **errp)
{
    DeviceState *dev = DEVICE(obj);

    if (dev->realized) {
        error_setg(errp, "Attempt to set link property '%s' on device '%s' "
                   "(type '%s') after it was realized",
                   name, dev->id, object_get_typename(obj));
    }
}

G
Gerd Hoffmann 已提交
41 42 43 44 45 46 47
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{
    void *ptr = dev;
    ptr += prop->offset;
    return ptr;
}

48 49
static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
50 51 52 53 54
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    int *ptr = qdev_get_prop_ptr(dev, prop);

55
    visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
56 57
}

58 59
static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
60 61 62 63 64
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    int *ptr = qdev_get_prop_ptr(dev, prop);

65
    if (dev->realized) {
66
        qdev_prop_set_after_realize(dev, name, errp);
67 68 69
        return;
    }

70
    visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
71 72
}

73 74
static void set_default_value_enum(Object *obj, const Property *prop)
{
75
    object_property_set_str(obj, prop->info->enum_table[prop->defval.i],
76 77 78
                            prop->name, &error_abort);
}

79 80
/* Bit */

M
Michael S. Tsirkin 已提交
81 82
static uint32_t qdev_get_prop_mask(Property *prop)
{
83
    assert(prop->info == &qdev_prop_bit);
M
Michael S. Tsirkin 已提交
84 85 86 87 88 89 90
    return 0x1 << prop->bitnr;
}

static void bit_prop_set(DeviceState *dev, Property *props, bool val)
{
    uint32_t *p = qdev_get_prop_ptr(dev, props);
    uint32_t mask = qdev_get_prop_mask(props);
E
Eduardo Habkost 已提交
91
    if (val) {
92
        *p |= mask;
E
Eduardo Habkost 已提交
93
    } else {
M
Michael S. Tsirkin 已提交
94
        *p &= ~mask;
E
Eduardo Habkost 已提交
95
    }
M
Michael S. Tsirkin 已提交
96 97
}

98 99
static void prop_get_bit(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
100
{
101
    DeviceState *dev = DEVICE(obj);
102 103 104 105
    Property *prop = opaque;
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
    bool value = (*p & qdev_get_prop_mask(prop)) != 0;

106
    visit_type_bool(v, name, &value, errp);
107 108
}

109 110
static void prop_set_bit(Object *obj, Visitor *v, const char *name,
                         void *opaque, Error **errp)
111
{
112
    DeviceState *dev = DEVICE(obj);
113 114 115 116
    Property *prop = opaque;
    Error *local_err = NULL;
    bool value;

117
    if (dev->realized) {
118
        qdev_prop_set_after_realize(dev, name, errp);
119 120 121
        return;
    }

122
    visit_type_bool(v, name, &value, &local_err);
123 124 125 126 127 128 129
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    bit_prop_set(dev, prop, value);
}

130 131
static void set_default_value_bool(Object *obj, const Property *prop)
{
132
    object_property_set_bool(obj, prop->defval.u, prop->name, &error_abort);
133 134
}

135
const PropertyInfo qdev_prop_bit = {
136
    .name  = "bool",
137
    .description = "on/off",
138 139
    .get   = prop_get_bit,
    .set   = prop_set_bit,
140
    .set_default_value = set_default_value_bool,
M
Michael S. Tsirkin 已提交
141 142
};

G
Gerd Hoffmann 已提交
143 144 145 146
/* Bit64 */

static uint64_t qdev_get_prop_mask64(Property *prop)
{
C
Cornelia Huck 已提交
147
    assert(prop->info == &qdev_prop_bit64);
G
Gonglei 已提交
148
    return 0x1ull << prop->bitnr;
G
Gerd Hoffmann 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161
}

static void bit64_prop_set(DeviceState *dev, Property *props, bool val)
{
    uint64_t *p = qdev_get_prop_ptr(dev, props);
    uint64_t mask = qdev_get_prop_mask64(props);
    if (val) {
        *p |= mask;
    } else {
        *p &= ~mask;
    }
}

162 163
static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
164 165 166 167 168 169
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *p = qdev_get_prop_ptr(dev, prop);
    bool value = (*p & qdev_get_prop_mask64(prop)) != 0;

170
    visit_type_bool(v, name, &value, errp);
G
Gerd Hoffmann 已提交
171 172
}

173 174
static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
175 176 177 178 179 180 181 182 183 184 185
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    Error *local_err = NULL;
    bool value;

    if (dev->realized) {
        qdev_prop_set_after_realize(dev, name, errp);
        return;
    }

186
    visit_type_bool(v, name, &value, &local_err);
G
Gerd Hoffmann 已提交
187 188 189 190 191 192 193
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
    bit64_prop_set(dev, prop, value);
}

194
const PropertyInfo qdev_prop_bit64 = {
G
Gerd Hoffmann 已提交
195 196 197 198
    .name  = "bool",
    .description = "on/off",
    .get   = prop_get_bit64,
    .set   = prop_set_bit64,
199
    .set_default_value = set_default_value_bool,
G
Gerd Hoffmann 已提交
200 201
};

202 203
/* --- bool --- */

204 205
static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
206 207 208 209 210
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    bool *ptr = qdev_get_prop_ptr(dev, prop);

211
    visit_type_bool(v, name, ptr, errp);
212 213
}

214 215
static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
216 217 218 219 220 221 222 223 224 225
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    bool *ptr = qdev_get_prop_ptr(dev, prop);

    if (dev->realized) {
        qdev_prop_set_after_realize(dev, name, errp);
        return;
    }

226
    visit_type_bool(v, name, ptr, errp);
227 228
}

229
const PropertyInfo qdev_prop_bool = {
230
    .name  = "bool",
231 232
    .get   = get_bool,
    .set   = set_bool,
233
    .set_default_value = set_default_value_bool,
234 235
};

J
Juan Quintela 已提交
236 237
/* --- 8bit integer --- */

238 239
static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      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
}

248 249
static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      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 258 259
        return;
    }

260
    visit_type_uint8(v, name, ptr, errp);
261 262
}

263 264
static void set_default_value_int(Object *obj, const Property *prop)
{
265
    object_property_set_int(obj, prop->defval.i, prop->name, &error_abort);
266 267
}

268 269 270 271 272
static void set_default_value_uint(Object *obj, const Property *prop)
{
    object_property_set_uint(obj, prop->defval.u, prop->name, &error_abort);
}

273
const PropertyInfo qdev_prop_uint8 = {
J
Juan Quintela 已提交
274
    .name  = "uint8",
275 276
    .get   = get_uint8,
    .set   = set_uint8,
277
    .set_default_value = set_default_value_uint,
J
Juan Quintela 已提交
278 279
};

G
Gerd Hoffmann 已提交
280 281
/* --- 16bit integer --- */

282 283
static void get_uint16(Object *obj, Visitor *v, const char *name,
                       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
}

292 293
static void set_uint16(Object *obj, Visitor *v, const char *name,
                       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 302 303
        return;
    }

304
    visit_type_uint16(v, name, ptr, errp);
305 306
}

307
const PropertyInfo qdev_prop_uint16 = {
G
Gerd Hoffmann 已提交
308
    .name  = "uint16",
309 310
    .get   = get_uint16,
    .set   = set_uint16,
311
    .set_default_value = set_default_value_uint,
G
Gerd Hoffmann 已提交
312 313 314 315
};

/* --- 32bit integer --- */

316 317
static void get_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
318 319 320
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
321
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
322

323
    visit_type_uint32(v, name, ptr, errp);
324 325
}

326 327
static void set_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
328 329 330
{
    DeviceState *dev = DEVICE(obj);
    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 336 337
        return;
    }

338
    visit_type_uint32(v, name, ptr, errp);
339 340
}

341 342
static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
343
{
344
    DeviceState *dev = DEVICE(obj);
345 346 347
    Property *prop = opaque;
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);

348
    visit_type_int32(v, name, ptr, errp);
349 350
}

351 352
static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      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 361 362
        return;
    }

363
    visit_type_int32(v, name, ptr, errp);
364 365
}

366
const PropertyInfo qdev_prop_uint32 = {
G
Gerd Hoffmann 已提交
367
    .name  = "uint32",
368 369
    .get   = get_uint32,
    .set   = set_uint32,
370
    .set_default_value = set_default_value_uint,
G
Gerd Hoffmann 已提交
371 372
};

373
const PropertyInfo qdev_prop_int32 = {
374
    .name  = "int32",
375 376
    .get   = get_int32,
    .set   = set_int32,
377
    .set_default_value = set_default_value_int,
378 379
};

B
Blue Swirl 已提交
380 381
/* --- 64bit integer --- */

382 383
static void get_uint64(Object *obj, Visitor *v, const char *name,
                       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
}

392 393
static void set_uint64(Object *obj, Visitor *v, const char *name,
                       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 402 403
        return;
    }

404
    visit_type_uint64(v, name, ptr, errp);
405 406
}

P
Peter Xu 已提交
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
static void get_int64(Object *obj, Visitor *v, const char *name,
                      void *opaque, Error **errp)
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    int64_t *ptr = qdev_get_prop_ptr(dev, prop);

    visit_type_int64(v, name, ptr, errp);
}

static void set_int64(Object *obj, Visitor *v, const char *name,
                      void *opaque, Error **errp)
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    int64_t *ptr = qdev_get_prop_ptr(dev, prop);

    if (dev->realized) {
        qdev_prop_set_after_realize(dev, name, errp);
        return;
    }

    visit_type_int64(v, name, ptr, errp);
}

432
const PropertyInfo qdev_prop_uint64 = {
B
Blue Swirl 已提交
433
    .name  = "uint64",
434 435
    .get   = get_uint64,
    .set   = set_uint64,
436
    .set_default_value = set_default_value_uint,
B
Blue Swirl 已提交
437 438
};

P
Peter Xu 已提交
439 440 441 442 443 444 445
const PropertyInfo qdev_prop_int64 = {
    .name  = "int64",
    .get   = get_int64,
    .set   = set_int64,
    .set_default_value = set_default_value_int,
};

G
Gerd Hoffmann 已提交
446 447
/* --- string --- */

P
Paolo Bonzini 已提交
448
static void release_string(Object *obj, const char *name, void *opaque)
449
{
P
Paolo Bonzini 已提交
450 451
    Property *prop = opaque;
    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
452 453
}

454 455
static void get_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
456
{
457
    DeviceState *dev = DEVICE(obj);
458 459 460 461 462
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);

    if (!*ptr) {
        char *str = (char *)"";
463
        visit_type_str(v, name, &str, errp);
464
    } else {
465
        visit_type_str(v, name, ptr, errp);
466 467 468
    }
}

469 470
static void set_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
471
{
472
    DeviceState *dev = DEVICE(obj);
473 474 475 476 477
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
    char *str;

478
    if (dev->realized) {
479
        qdev_prop_set_after_realize(dev, name, errp);
480 481 482
        return;
    }

483
    visit_type_str(v, name, &str, &local_err);
484 485 486 487
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
488
    g_free(*ptr);
489 490 491
    *ptr = str;
}

492
const PropertyInfo qdev_prop_string = {
493
    .name  = "str",
P
Paolo Bonzini 已提交
494
    .release = release_string,
495 496
    .get   = get_string,
    .set   = set_string,
G
Gerd Hoffmann 已提交
497 498
};

G
Gerd Hoffmann 已提交
499 500
/* --- pointer --- */

501
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
502
const PropertyInfo qdev_prop_ptr = {
G
Gerd Hoffmann 已提交
503 504 505 506 507 508 509 510 511 512
    .name  = "ptr",
};

/* --- mac address --- */

/*
 * accepted syntax versions:
 *   01:02:03:04:05:06
 *   01-02-03-04-05-06
 */
513 514
static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
G
Gerd Hoffmann 已提交
515
{
516 517
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
G
Gerd Hoffmann 已提交
518
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
519 520 521 522 523 524 525
    char buffer[2 * 6 + 5 + 1];
    char *p = buffer;

    snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
             mac->a[0], mac->a[1], mac->a[2],
             mac->a[3], mac->a[4], mac->a[5]);

526
    visit_type_str(v, name, &p, errp);
527 528
}

529 530
static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
531 532 533 534 535
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
G
Gerd Hoffmann 已提交
536
    int i, pos;
537 538
    char *str, *p;

539
    if (dev->realized) {
540
        qdev_prop_set_after_realize(dev, name, errp);
541 542 543
        return;
    }

544
    visit_type_str(v, name, &str, &local_err);
545 546 547 548
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
G
Gerd Hoffmann 已提交
549 550

    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
E
Eduardo Habkost 已提交
551
        if (!qemu_isxdigit(str[pos])) {
552
            goto inval;
E
Eduardo Habkost 已提交
553 554
        }
        if (!qemu_isxdigit(str[pos+1])) {
555
            goto inval;
E
Eduardo Habkost 已提交
556
        }
G
Gerd Hoffmann 已提交
557
        if (i == 5) {
E
Eduardo Habkost 已提交
558
            if (str[pos+2] != '\0') {
559
                goto inval;
E
Eduardo Habkost 已提交
560
            }
G
Gerd Hoffmann 已提交
561
        } else {
E
Eduardo Habkost 已提交
562
            if (str[pos+2] != ':' && str[pos+2] != '-') {
563
                goto inval;
E
Eduardo Habkost 已提交
564
            }
G
Gerd Hoffmann 已提交
565 566
        }
        mac->a[i] = strtol(str+pos, &p, 16);
G
Gerd Hoffmann 已提交
567
    }
D
dunrong huang 已提交
568
    g_free(str);
569
    return;
G
Gerd Hoffmann 已提交
570

571 572
inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
573
    g_free(str);
G
Gerd Hoffmann 已提交
574 575
}

576
const PropertyInfo qdev_prop_macaddr = {
577
    .name  = "str",
578
    .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
579 580
    .get   = get_mac,
    .set   = set_mac,
G
Gerd Hoffmann 已提交
581 582
};

583 584
/* --- on/off/auto --- */

585
const PropertyInfo qdev_prop_on_off_auto = {
586 587 588 589 590
    .name = "OnOffAuto",
    .description = "on/off/auto",
    .enum_table = OnOffAuto_lookup,
    .get = get_enum,
    .set = set_enum,
591
    .set_default_value = set_default_value_enum,
592 593
};

594 595
/* --- lost tick policy --- */

596 597
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));

598
const PropertyInfo qdev_prop_losttickpolicy = {
599
    .name  = "LostTickPolicy",
600
    .enum_table  = LostTickPolicy_lookup,
601 602
    .get   = get_enum,
    .set   = set_enum,
603
    .set_default_value = set_default_value_enum,
604 605
};

606 607 608 609
/* --- Block device error handling policy --- */

QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));

610
const PropertyInfo qdev_prop_blockdev_on_error = {
611 612 613 614 615 616
    .name = "BlockdevOnError",
    .description = "Error handling policy, "
                   "report/ignore/enospc/stop/auto",
    .enum_table = BlockdevOnError_lookup,
    .get = get_enum,
    .set = set_enum,
617
    .set_default_value = set_default_value_enum,
618 619
};

620 621
/* --- BIOS CHS translation */

622
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
623

624
const PropertyInfo qdev_prop_bios_chs_trans = {
625
    .name = "BiosAtaTranslation",
626 627
    .description = "Logical CHS translation algorithm, "
                   "auto/none/lba/large/rechs",
628
    .enum_table = BiosAtaTranslation_lookup,
629 630
    .get = get_enum,
    .set = set_enum,
631
    .set_default_value = set_default_value_enum,
632 633
};

J
John Snow 已提交
634 635
/* --- FDC default drive types */

636
const PropertyInfo qdev_prop_fdc_drive_type = {
J
John Snow 已提交
637 638 639 640 641
    .name = "FdcDriveType",
    .description = "FDC drive type, "
                   "144/288/120/none/auto",
    .enum_table = FloppyDriveType_lookup,
    .get = get_enum,
642 643
    .set = set_enum,
    .set_default_value = set_default_value_enum,
J
John Snow 已提交
644 645
};

646 647 648 649 650
/* --- pci address --- */

/*
 * bus-local address, i.e. "$slot" or "$slot.$fn"
 */
651 652
static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
653
{
654 655
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
656
    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
657
    unsigned int slot, fn, n;
658
    Error *local_err = NULL;
D
dunrong huang 已提交
659
    char *str;
660

661
    if (dev->realized) {
662
        qdev_prop_set_after_realize(dev, name, errp);
663 664 665
        return;
    }

666
    visit_type_str(v, name, &str, &local_err);
667
    if (local_err) {
668
        error_free(local_err);
669
        local_err = NULL;
670
        visit_type_int32(v, name, &value, &local_err);
671 672 673
        if (local_err) {
            error_propagate(errp, local_err);
        } else if (value < -1 || value > 255) {
674 675
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                       name ? name : "null", "pci_devfn");
676 677 678 679
        } else {
            *ptr = value;
        }
        return;
680
    }
681 682 683 684

    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
        fn = 0;
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
685
            goto invalid;
686 687
        }
    }
688 689 690
    if (str[n] != '\0' || fn > 7 || slot > 31) {
        goto invalid;
    }
691
    *ptr = slot << 3 | fn;
D
dunrong huang 已提交
692
    g_free(str);
693 694 695 696
    return;

invalid:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
697
    g_free(str);
698 699
}

E
Eduardo Habkost 已提交
700 701
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
                           size_t len)
702
{
703
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
704

B
Blue Swirl 已提交
705
    if (*ptr == -1) {
706 707 708 709 710 711
        return snprintf(dest, len, "<unset>");
    } else {
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
    }
}

712
const PropertyInfo qdev_prop_pci_devfn = {
713
    .name  = "int32",
714
    .description = "Slot and optional function number, example: 06.0 or 06",
715
    .print = print_pci_devfn,
716
    .get   = get_int32,
717
    .set   = set_pci_devfn,
718
    .set_default_value = set_default_value_int,
719 720
};

721 722
/* --- blocksize --- */

723 724
static void set_blocksize(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
725 726 727
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
728
    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
729
    Error *local_err = NULL;
730 731
    const int64_t min = 512;
    const int64_t max = 32768;
732

733
    if (dev->realized) {
734
        qdev_prop_set_after_realize(dev, name, errp);
735 736 737
        return;
    }

738
    visit_type_uint16(v, name, &value, &local_err);
739 740 741 742
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
743 744
    /* value of 0 means "unset" */
    if (value && (value < min || value > max)) {
745 746
        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
                   dev->id ? : "", name, (int64_t)value, min, max);
747 748 749 750 751
        return;
    }

    /* We rely on power-of-2 blocksizes for bitmasks */
    if ((value & (value - 1)) != 0) {
752 753 754
        error_setg(errp,
                  "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
                  dev->id ?: "", name, (int64_t)value);
755 756 757 758 759 760
        return;
    }

    *ptr = value;
}

761
const PropertyInfo qdev_prop_blocksize = {
762
    .name  = "uint16",
763
    .description = "A power of two between 512 and 32768",
764
    .get   = get_uint16,
765
    .set   = set_blocksize,
766
    .set_default_value = set_default_value_uint,
767 768
};

769 770
/* --- pci host address --- */

771 772
static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
773 774 775 776
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
777
    char buffer[] = "ffff:ff:ff.f";
778 779 780
    char *p = buffer;
    int rc = 0;

781 782
    /*
     * Catch "invalid" device reference from vfio-pci and allow the
S
Stefan Weil 已提交
783
     * default buffer representing the non-existent device to be used.
784 785 786 787 788 789
     */
    if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
        rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
                      addr->domain, addr->bus, addr->slot, addr->function);
        assert(rc == sizeof(buffer) - 1);
    }
790

791
    visit_type_str(v, name, &p, errp);
792 793 794 795 796 797
}

/*
 * Parse [<domain>:]<bus>:<slot>.<func>
 *   if <domain> is not supplied, it's assumed to be 0.
 */
798 799
static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
800 801 802 803 804 805 806 807 808 809 810
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
    char *str, *p;
    char *e;
    unsigned long val;
    unsigned long dom = 0, bus = 0;
    unsigned int slot = 0, func = 0;

811
    if (dev->realized) {
812
        qdev_prop_set_after_realize(dev, name, errp);
813 814 815
        return;
    }

816
    visit_type_str(v, name, &str, &local_err);
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    p = str;
    val = strtoul(p, &e, 16);
    if (e == p || *e != ':') {
        goto inval;
    }
    bus = val;

    p = e + 1;
    val = strtoul(p, &e, 16);
    if (e == p) {
        goto inval;
    }
    if (*e == ':') {
        dom = bus;
        bus = val;
        p = e + 1;
        val = strtoul(p, &e, 16);
        if (e == p) {
            goto inval;
        }
    }
    slot = val;

    if (*e != '.') {
        goto inval;
    }
    p = e + 1;
    val = strtoul(p, &e, 10);
    if (e == p) {
        goto inval;
    }
    func = val;

    if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
        goto inval;
    }

    if (*e) {
        goto inval;
    }

    addr->domain = dom;
    addr->bus = bus;
    addr->slot = slot;
    addr->function = func;

    g_free(str);
    return;

inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
    g_free(str);
}

876
const PropertyInfo qdev_prop_pci_host_devaddr = {
877
    .name = "str",
878 879
    .description = "Address (bus/device/function) of "
                   "the host device, example: 04:10.0",
880 881 882 883
    .get = get_pci_host_devaddr,
    .set = set_pci_host_devaddr,
};

884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
/* --- support for array properties --- */

/* Used as an opaque for the object properties we add for each
 * array element. Note that the struct Property must be first
 * in the struct so that a pointer to this works as the opaque
 * for the underlying element's property hooks as well as for
 * our own release callback.
 */
typedef struct {
    struct Property prop;
    char *propname;
    ObjectPropertyRelease *release;
} ArrayElementProperty;

/* object property release callback for array element properties:
 * we call the underlying element's property release hook, and
 * then free the memory we allocated when we added the property.
 */
static void array_element_release(Object *obj, const char *name, void *opaque)
{
    ArrayElementProperty *p = opaque;
    if (p->release) {
        p->release(obj, name, opaque);
    }
    g_free(p->propname);
    g_free(p);
}

912 913
static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
                              void *opaque, Error **errp)
914 915 916 917 918 919 920 921 922 923
{
    /* Setter for the property which defines the length of a
     * variable-sized property array. As well as actually setting the
     * array-length field in the device struct, we have to create the
     * array itself and dynamically add the corresponding properties.
     */
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint32_t *alenptr = qdev_get_prop_ptr(dev, prop);
    void **arrayptr = (void *)dev + prop->arrayoffset;
924
    Error *local_err = NULL;
925 926 927 928 929
    void *eltptr;
    const char *arrayname;
    int i;

    if (dev->realized) {
930
        qdev_prop_set_after_realize(dev, name, errp);
931 932 933 934 935 936 937
        return;
    }
    if (*alenptr) {
        error_setg(errp, "array size property %s may not be set more than once",
                   name);
        return;
    }
938
    visit_type_uint32(v, name, alenptr, &local_err);
939 940
    if (local_err) {
        error_propagate(errp, local_err);
941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
        return;
    }
    if (!*alenptr) {
        return;
    }

    /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
     * strip it off so we can get the name of the array itself.
     */
    assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
                   strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
    arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);

    /* Note that it is the responsibility of the individual device's deinit
     * to free the array proper.
     */
    *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
    for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
        char *propname = g_strdup_printf("%s[%d]", arrayname, i);
        ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
        arrayprop->release = prop->arrayinfo->release;
        arrayprop->propname = propname;
        arrayprop->prop.info = prop->arrayinfo;
        arrayprop->prop.name = propname;
        /* This ugly piece of pointer arithmetic sets up the offset so
         * that when the underlying get/set hooks call qdev_get_prop_ptr
         * they get the right answer despite the array element not actually
         * being inside the device struct.
         */
        arrayprop->prop.offset = eltptr - (void *)dev;
        assert(qdev_get_prop_ptr(dev, &arrayprop->prop) == eltptr);
        object_property_add(obj, propname,
                            arrayprop->prop.info->name,
                            arrayprop->prop.info->get,
                            arrayprop->prop.info->set,
                            array_element_release,
977 978 979
                            arrayprop, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
980 981 982 983 984
            return;
        }
    }
}

985
const PropertyInfo qdev_prop_arraylen = {
986 987 988
    .name = "uint32",
    .get = get_uint32,
    .set = set_prop_arraylen,
989
    .set_default_value = set_default_value_uint,
990 991
};

G
Gerd Hoffmann 已提交
992 993 994 995
/* --- public helpers --- */

static Property *qdev_prop_walk(Property *props, const char *name)
{
E
Eduardo Habkost 已提交
996
    if (!props) {
G
Gerd Hoffmann 已提交
997
        return NULL;
E
Eduardo Habkost 已提交
998
    }
G
Gerd Hoffmann 已提交
999
    while (props->name) {
E
Eduardo Habkost 已提交
1000
        if (strcmp(props->name, name) == 0) {
G
Gerd Hoffmann 已提交
1001
            return props;
E
Eduardo Habkost 已提交
1002
        }
G
Gerd Hoffmann 已提交
1003 1004 1005 1006 1007 1008 1009
        props++;
    }
    return NULL;
}

static Property *qdev_prop_find(DeviceState *dev, const char *name)
{
1010
    ObjectClass *class;
G
Gerd Hoffmann 已提交
1011 1012 1013
    Property *prop;

    /* device properties */
1014 1015 1016 1017 1018 1019 1020 1021
    class = object_get_class(OBJECT(dev));
    do {
        prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
        if (prop) {
            return prop;
        }
        class = object_class_get_parent(class);
    } while (class != object_class_by_name(TYPE_DEVICE));
G
Gerd Hoffmann 已提交
1022 1023 1024 1025

    return NULL;
}

1026 1027 1028 1029 1030
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
                                    Property *prop, const char *value)
{
    switch (ret) {
    case -EEXIST:
1031
        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
1032
                  object_get_typename(OBJECT(dev)), prop->name, value);
1033 1034 1035
        break;
    default:
    case -EINVAL:
1036 1037
        error_setg(errp, QERR_PROPERTY_VALUE_BAD,
                   object_get_typename(OBJECT(dev)), prop->name, value);
1038 1039
        break;
    case -ENOENT:
1040
        error_setg(errp, "Property '%s.%s' can't find value '%s'",
1041
                  object_get_typename(OBJECT(dev)), prop->name, value);
1042 1043 1044 1045 1046 1047
        break;
    case 0:
        break;
    }
}

1048 1049
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
{
1050
    object_property_set_bool(OBJECT(dev), value, name, &error_abort);
1051 1052
}

J
Juan Quintela 已提交
1053 1054
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
{
1055
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
J
Juan Quintela 已提交
1056 1057
}

G
Gerd Hoffmann 已提交
1058 1059
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
{
1060
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
1061 1062 1063 1064
}

void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
{
1065
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
1066 1067
}

1068 1069
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
{
1070
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
1071 1072
}

B
Blue Swirl 已提交
1073 1074
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
{
1075
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
B
Blue Swirl 已提交
1076 1077
}

1078
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
1079
{
1080
    object_property_set_str(OBJECT(dev), value, name, &error_abort);
1081 1082
}

1083 1084
void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
                           const uint8_t *value)
G
Gerd Hoffmann 已提交
1085
{
P
Paolo Bonzini 已提交
1086 1087 1088 1089
    char str[2 * 6 + 5 + 1];
    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
             value[0], value[1], value[2], value[3], value[4], value[5]);

1090
    object_property_set_str(OBJECT(dev), str, name, &error_abort);
G
Gerd Hoffmann 已提交
1091 1092
}

P
Paolo Bonzini 已提交
1093
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1094
{
P
Paolo Bonzini 已提交
1095 1096 1097 1098
    Property *prop;

    prop = qdev_prop_find(dev, name);
    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1099
                            name, &error_abort);
1100 1101
}

G
Gerd Hoffmann 已提交
1102 1103
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
{
1104 1105 1106 1107 1108 1109 1110
    Property *prop;
    void **ptr;

    prop = qdev_prop_find(dev, name);
    assert(prop && prop->info == &qdev_prop_ptr);
    ptr = qdev_get_prop_ptr(dev, prop);
    *ptr = value;
G
Gerd Hoffmann 已提交
1111 1112
}

1113
static GList *global_props;
1114

1115
void qdev_prop_register_global(GlobalProperty *prop)
1116
{
1117
    global_props = g_list_append(global_props, prop);
1118 1119
}

1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
void register_compat_prop(const char *driver,
                          const char *property,
                          const char *value)
{
    GlobalProperty *p = g_new0(GlobalProperty, 1);

    /* Any compat_props must never cause error */
    p->errp = &error_abort;
    p->driver = driver;
    p->property = property;
    p->value = value;
    qdev_prop_register_global(p);
}

1134 1135 1136 1137 1138 1139 1140
void register_compat_props_array(GlobalProperty *prop)
{
    for (; prop && prop->driver; prop++) {
        register_compat_prop(prop->driver, prop->property, prop->value);
    }
}

1141
void qdev_prop_register_global_list(GlobalProperty *props)
1142
{
1143
    int i;
1144

1145 1146
    for (i = 0; props[i].driver != NULL; i++) {
        qdev_prop_register_global(props+i);
1147
    }
1148 1149
}

1150
int qdev_prop_check_globals(void)
1151
{
1152
    GList *l;
1153 1154
    int ret = 0;

1155 1156
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
        ObjectClass *oc;
        DeviceClass *dc;
        if (prop->used) {
            continue;
        }
        if (!prop->user_provided) {
            continue;
        }
        oc = object_class_by_name(prop->driver);
        oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
        if (!oc) {
1168 1169
            warn_report("global %s.%s has invalid class name",
                        prop->driver, prop->property);
1170 1171 1172 1173 1174
            ret = 1;
            continue;
        }
        dc = DEVICE_CLASS(oc);
        if (!dc->hotpluggable && !prop->used) {
1175 1176
            warn_report("global %s.%s=%s not used",
                        prop->driver, prop->property, prop->value);
1177
            ret = 1;
1178 1179 1180 1181 1182 1183
            continue;
        }
    }
    return ret;
}

1184
void qdev_prop_set_globals(DeviceState *dev)
1185
{
1186
    GList *l;
1187

1188 1189
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1190 1191
        Error *err = NULL;

1192
        if (object_dynamic_cast(OBJECT(dev), prop->driver) == NULL) {
1193 1194
            continue;
        }
1195
        prop->used = true;
P
Paolo Bonzini 已提交
1196
        object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
1197
        if (err != NULL) {
1198 1199
            error_prepend(&err, "can't apply global %s.%s=%s: ",
                          prop->driver, prop->property, prop->value);
1200
            if (!dev->hotplugged && prop->errp) {
1201 1202 1203
                error_propagate(prop->errp, err);
            } else {
                assert(prop->user_provided);
1204
                warn_report_err(err);
1205
            }
1206 1207 1208 1209
        }
    }
}

1210 1211
/* --- 64bit unsigned int 'size' type --- */

1212 1213
static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1214 1215 1216 1217 1218
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1219
    visit_type_size(v, name, ptr, errp);
1220 1221
}

1222 1223
static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1224 1225 1226 1227 1228
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1229
    visit_type_size(v, name, ptr, errp);
1230 1231
}

1232
const PropertyInfo qdev_prop_size = {
1233 1234 1235
    .name  = "size",
    .get = get_size,
    .set = set_size,
1236
    .set_default_value = set_default_value_uint,
1237
};
F
Fam Zheng 已提交
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251

/* --- object link property --- */

static void create_link_property(Object *obj, Property *prop, Error **errp)
{
    Object **child = qdev_get_prop_ptr(DEVICE(obj), prop);

    object_property_add_link(obj, prop->name, prop->link_type,
                             child,
                             qdev_prop_allow_set_link_before_realize,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             errp);
}

1252
const PropertyInfo qdev_prop_link = {
F
Fam Zheng 已提交
1253 1254 1255
    .name = "link",
    .create = create_link_property,
};