qdev-properties.c 31.9 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 30 31 32 33 34 35 36 37 38 39
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
                                             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 已提交
40 41 42 43 44 45 46
void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
{
    void *ptr = dev;
    ptr += prop->offset;
    return ptr;
}

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

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

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

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

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

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

78 79
/* Bit */

M
Michael S. Tsirkin 已提交
80 81
static uint32_t qdev_get_prop_mask(Property *prop)
{
82
    assert(prop->info == &qdev_prop_bit);
M
Michael S. Tsirkin 已提交
83 84 85 86 87 88 89
    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 已提交
90
    if (val) {
91
        *p |= mask;
E
Eduardo Habkost 已提交
92
    } else {
M
Michael S. Tsirkin 已提交
93
        *p &= ~mask;
E
Eduardo Habkost 已提交
94
    }
M
Michael S. Tsirkin 已提交
95 96
}

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

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

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

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

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

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

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

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

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

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;
    }
}

161 162
static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
163 164 165 166 167 168
{
    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;

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

172 173
static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
                           void *opaque, Error **errp)
G
Gerd Hoffmann 已提交
174 175 176 177 178 179 180 181 182 183 184
{
    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;
    }

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

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

201 202
/* --- bool --- */

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

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

213 214
static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
215 216 217 218 219 220 221 222 223 224
{
    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;
    }

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

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

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

237 238
static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
239
{
240
    DeviceState *dev = DEVICE(obj);
241
    Property *prop = opaque;
242
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
243

244
    visit_type_uint8(v, name, ptr, errp);
245 246
}

247 248
static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
249
{
250
    DeviceState *dev = DEVICE(obj);
251
    Property *prop = opaque;
252
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
253

254
    if (dev->realized) {
255
        qdev_prop_set_after_realize(dev, name, errp);
256 257 258
        return;
    }

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

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

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

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

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

281 282
static void get_uint16(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
283
{
284
    DeviceState *dev = DEVICE(obj);
285
    Property *prop = opaque;
286
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
287

288
    visit_type_uint16(v, name, ptr, errp);
289 290
}

291 292
static void set_uint16(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
293
{
294
    DeviceState *dev = DEVICE(obj);
295
    Property *prop = opaque;
296
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
297

298
    if (dev->realized) {
299
        qdev_prop_set_after_realize(dev, name, errp);
300 301 302
        return;
    }

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

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

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

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

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

325 326
static void set_uint32(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
327 328 329
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
330
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
331

332
    if (dev->realized) {
333
        qdev_prop_set_after_realize(dev, name, errp);
334 335 336
        return;
    }

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

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

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

350 351
static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
                      Error **errp)
352
{
353
    DeviceState *dev = DEVICE(obj);
354
    Property *prop = opaque;
355
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
356

357
    if (dev->realized) {
358
        qdev_prop_set_after_realize(dev, name, errp);
359 360 361
        return;
    }

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

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

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

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

381 382
static void get_uint64(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
383
{
384
    DeviceState *dev = DEVICE(obj);
385
    Property *prop = opaque;
386
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
387

388
    visit_type_uint64(v, name, ptr, errp);
389 390
}

391 392
static void set_uint64(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
393
{
394
    DeviceState *dev = DEVICE(obj);
395
    Property *prop = opaque;
396
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
397

398
    if (dev->realized) {
399
        qdev_prop_set_after_realize(dev, name, errp);
400 401 402
        return;
    }

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

B
Blue Swirl 已提交
406 407
PropertyInfo qdev_prop_uint64 = {
    .name  = "uint64",
408 409
    .get   = get_uint64,
    .set   = set_uint64,
410
    .set_default_value = set_default_value_uint,
B
Blue Swirl 已提交
411 412
};

G
Gerd Hoffmann 已提交
413 414
/* --- string --- */

P
Paolo Bonzini 已提交
415
static void release_string(Object *obj, const char *name, void *opaque)
416
{
P
Paolo Bonzini 已提交
417 418
    Property *prop = opaque;
    g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
419 420
}

421 422
static void get_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
423
{
424
    DeviceState *dev = DEVICE(obj);
425 426 427 428 429
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);

    if (!*ptr) {
        char *str = (char *)"";
430
        visit_type_str(v, name, &str, errp);
431
    } else {
432
        visit_type_str(v, name, ptr, errp);
433 434 435
    }
}

436 437
static void set_string(Object *obj, Visitor *v, const char *name,
                       void *opaque, Error **errp)
438
{
439
    DeviceState *dev = DEVICE(obj);
440 441 442 443 444
    Property *prop = opaque;
    char **ptr = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
    char *str;

445
    if (dev->realized) {
446
        qdev_prop_set_after_realize(dev, name, errp);
447 448 449
        return;
    }

450
    visit_type_str(v, name, &str, &local_err);
451 452 453 454
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
455
    g_free(*ptr);
456 457 458
    *ptr = str;
}

G
Gerd Hoffmann 已提交
459
PropertyInfo qdev_prop_string = {
460
    .name  = "str",
P
Paolo Bonzini 已提交
461
    .release = release_string,
462 463
    .get   = get_string,
    .set   = set_string,
G
Gerd Hoffmann 已提交
464 465
};

G
Gerd Hoffmann 已提交
466 467
/* --- pointer --- */

468
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
G
Gerd Hoffmann 已提交
469 470 471 472 473 474 475 476 477 478 479
PropertyInfo qdev_prop_ptr = {
    .name  = "ptr",
};

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

/*
 * accepted syntax versions:
 *   01:02:03:04:05:06
 *   01-02-03-04-05-06
 */
480 481
static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
G
Gerd Hoffmann 已提交
482
{
483 484
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
G
Gerd Hoffmann 已提交
485
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
486 487 488 489 490 491 492
    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]);

493
    visit_type_str(v, name, &p, errp);
494 495
}

496 497
static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
                    Error **errp)
498 499 500 501 502
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
    Error *local_err = NULL;
G
Gerd Hoffmann 已提交
503
    int i, pos;
504 505
    char *str, *p;

506
    if (dev->realized) {
507
        qdev_prop_set_after_realize(dev, name, errp);
508 509 510
        return;
    }

511
    visit_type_str(v, name, &str, &local_err);
512 513 514 515
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
G
Gerd Hoffmann 已提交
516 517

    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
E
Eduardo Habkost 已提交
518
        if (!qemu_isxdigit(str[pos])) {
519
            goto inval;
E
Eduardo Habkost 已提交
520 521
        }
        if (!qemu_isxdigit(str[pos+1])) {
522
            goto inval;
E
Eduardo Habkost 已提交
523
        }
G
Gerd Hoffmann 已提交
524
        if (i == 5) {
E
Eduardo Habkost 已提交
525
            if (str[pos+2] != '\0') {
526
                goto inval;
E
Eduardo Habkost 已提交
527
            }
G
Gerd Hoffmann 已提交
528
        } else {
E
Eduardo Habkost 已提交
529
            if (str[pos+2] != ':' && str[pos+2] != '-') {
530
                goto inval;
E
Eduardo Habkost 已提交
531
            }
G
Gerd Hoffmann 已提交
532 533
        }
        mac->a[i] = strtol(str+pos, &p, 16);
G
Gerd Hoffmann 已提交
534
    }
D
dunrong huang 已提交
535
    g_free(str);
536
    return;
G
Gerd Hoffmann 已提交
537

538 539
inval:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
540
    g_free(str);
G
Gerd Hoffmann 已提交
541 542 543
}

PropertyInfo qdev_prop_macaddr = {
544
    .name  = "str",
545
    .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
546 547
    .get   = get_mac,
    .set   = set_mac,
G
Gerd Hoffmann 已提交
548 549
};

550 551 552 553 554 555 556 557
/* --- on/off/auto --- */

PropertyInfo qdev_prop_on_off_auto = {
    .name = "OnOffAuto",
    .description = "on/off/auto",
    .enum_table = OnOffAuto_lookup,
    .get = get_enum,
    .set = set_enum,
558
    .set_default_value = set_default_value_enum,
559 560
};

561 562
/* --- lost tick policy --- */

563 564
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));

565
PropertyInfo qdev_prop_losttickpolicy = {
566
    .name  = "LostTickPolicy",
567
    .enum_table  = LostTickPolicy_lookup,
568 569
    .get   = get_enum,
    .set   = set_enum,
570
    .set_default_value = set_default_value_enum,
571 572
};

573 574 575 576 577 578 579 580 581 582 583
/* --- Block device error handling policy --- */

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

PropertyInfo qdev_prop_blockdev_on_error = {
    .name = "BlockdevOnError",
    .description = "Error handling policy, "
                   "report/ignore/enospc/stop/auto",
    .enum_table = BlockdevOnError_lookup,
    .get = get_enum,
    .set = set_enum,
584
    .set_default_value = set_default_value_enum,
585 586
};

587 588
/* --- BIOS CHS translation */

589
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
590 591

PropertyInfo qdev_prop_bios_chs_trans = {
592
    .name = "BiosAtaTranslation",
593 594
    .description = "Logical CHS translation algorithm, "
                   "auto/none/lba/large/rechs",
595
    .enum_table = BiosAtaTranslation_lookup,
596 597
    .get = get_enum,
    .set = set_enum,
598
    .set_default_value = set_default_value_enum,
599 600
};

J
John Snow 已提交
601 602 603 604 605 606 607 608
/* --- FDC default drive types */

PropertyInfo qdev_prop_fdc_drive_type = {
    .name = "FdcDriveType",
    .description = "FDC drive type, "
                   "144/288/120/none/auto",
    .enum_table = FloppyDriveType_lookup,
    .get = get_enum,
609 610
    .set = set_enum,
    .set_default_value = set_default_value_enum,
J
John Snow 已提交
611 612
};

613 614 615 616 617
/* --- pci address --- */

/*
 * bus-local address, i.e. "$slot" or "$slot.$fn"
 */
618 619
static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
620
{
621 622
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
623
    int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
624
    unsigned int slot, fn, n;
625
    Error *local_err = NULL;
D
dunrong huang 已提交
626
    char *str;
627

628
    if (dev->realized) {
629
        qdev_prop_set_after_realize(dev, name, errp);
630 631 632
        return;
    }

633
    visit_type_str(v, name, &str, &local_err);
634
    if (local_err) {
635
        error_free(local_err);
636
        local_err = NULL;
637
        visit_type_int32(v, name, &value, &local_err);
638 639 640
        if (local_err) {
            error_propagate(errp, local_err);
        } else if (value < -1 || value > 255) {
641 642
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                       name ? name : "null", "pci_devfn");
643 644 645 646
        } else {
            *ptr = value;
        }
        return;
647
    }
648 649 650 651

    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
        fn = 0;
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
652
            goto invalid;
653 654
        }
    }
655 656 657
    if (str[n] != '\0' || fn > 7 || slot > 31) {
        goto invalid;
    }
658
    *ptr = slot << 3 | fn;
D
dunrong huang 已提交
659
    g_free(str);
660 661 662 663
    return;

invalid:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
D
dunrong huang 已提交
664
    g_free(str);
665 666
}

E
Eduardo Habkost 已提交
667 668
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
                           size_t len)
669
{
670
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
671

B
Blue Swirl 已提交
672
    if (*ptr == -1) {
673 674 675 676 677 678 679
        return snprintf(dest, len, "<unset>");
    } else {
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
    }
}

PropertyInfo qdev_prop_pci_devfn = {
680
    .name  = "int32",
681
    .description = "Slot and optional function number, example: 06.0 or 06",
682
    .print = print_pci_devfn,
683
    .get   = get_int32,
684
    .set   = set_pci_devfn,
685
    .set_default_value = set_default_value_int,
686 687
};

688 689
/* --- blocksize --- */

690 691
static void set_blocksize(Object *obj, Visitor *v, const char *name,
                          void *opaque, Error **errp)
692 693 694
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
695
    uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
696
    Error *local_err = NULL;
697 698
    const int64_t min = 512;
    const int64_t max = 32768;
699

700
    if (dev->realized) {
701
        qdev_prop_set_after_realize(dev, name, errp);
702 703 704
        return;
    }

705
    visit_type_uint16(v, name, &value, &local_err);
706 707 708 709
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }
710 711
    /* value of 0 means "unset" */
    if (value && (value < min || value > max)) {
712 713
        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
                   dev->id ? : "", name, (int64_t)value, min, max);
714 715 716 717 718
        return;
    }

    /* We rely on power-of-2 blocksizes for bitmasks */
    if ((value & (value - 1)) != 0) {
719 720 721
        error_setg(errp,
                  "Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
                  dev->id ?: "", name, (int64_t)value);
722 723 724 725 726 727 728
        return;
    }

    *ptr = value;
}

PropertyInfo qdev_prop_blocksize = {
729
    .name  = "uint16",
730
    .description = "A power of two between 512 and 32768",
731
    .get   = get_uint16,
732
    .set   = set_blocksize,
733
    .set_default_value = set_default_value_uint,
734 735
};

736 737
/* --- pci host address --- */

738 739
static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
740 741 742 743
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
744
    char buffer[] = "ffff:ff:ff.f";
745 746 747
    char *p = buffer;
    int rc = 0;

748 749
    /*
     * Catch "invalid" device reference from vfio-pci and allow the
S
Stefan Weil 已提交
750
     * default buffer representing the non-existent device to be used.
751 752 753 754 755 756
     */
    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);
    }
757

758
    visit_type_str(v, name, &p, errp);
759 760 761 762 763 764
}

/*
 * Parse [<domain>:]<bus>:<slot>.<func>
 *   if <domain> is not supplied, it's assumed to be 0.
 */
765 766
static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
                                 void *opaque, Error **errp)
767 768 769 770 771 772 773 774 775 776 777
{
    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;

778
    if (dev->realized) {
779
        qdev_prop_set_after_realize(dev, name, errp);
780 781 782
        return;
    }

783
    visit_type_str(v, name, &str, &local_err);
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 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
    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);
}

PropertyInfo qdev_prop_pci_host_devaddr = {
844
    .name = "str",
845 846
    .description = "Address (bus/device/function) of "
                   "the host device, example: 04:10.0",
847 848 849 850
    .get = get_pci_host_devaddr,
    .set = set_pci_host_devaddr,
};

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 876 877 878
/* --- 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);
}

879 880
static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
                              void *opaque, Error **errp)
881 882 883 884 885 886 887 888 889 890
{
    /* 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;
891
    Error *local_err = NULL;
892 893 894 895 896
    void *eltptr;
    const char *arrayname;
    int i;

    if (dev->realized) {
897
        qdev_prop_set_after_realize(dev, name, errp);
898 899 900 901 902 903 904
        return;
    }
    if (*alenptr) {
        error_setg(errp, "array size property %s may not be set more than once",
                   name);
        return;
    }
905
    visit_type_uint32(v, name, alenptr, &local_err);
906 907
    if (local_err) {
        error_propagate(errp, local_err);
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943
        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,
944 945 946
                            arrayprop, &local_err);
        if (local_err) {
            error_propagate(errp, local_err);
947 948 949 950 951 952 953 954 955
            return;
        }
    }
}

PropertyInfo qdev_prop_arraylen = {
    .name = "uint32",
    .get = get_uint32,
    .set = set_prop_arraylen,
956
    .set_default_value = set_default_value_uint,
957 958
};

G
Gerd Hoffmann 已提交
959 960 961 962
/* --- public helpers --- */

static Property *qdev_prop_walk(Property *props, const char *name)
{
E
Eduardo Habkost 已提交
963
    if (!props) {
G
Gerd Hoffmann 已提交
964
        return NULL;
E
Eduardo Habkost 已提交
965
    }
G
Gerd Hoffmann 已提交
966
    while (props->name) {
E
Eduardo Habkost 已提交
967
        if (strcmp(props->name, name) == 0) {
G
Gerd Hoffmann 已提交
968
            return props;
E
Eduardo Habkost 已提交
969
        }
G
Gerd Hoffmann 已提交
970 971 972 973 974 975 976
        props++;
    }
    return NULL;
}

static Property *qdev_prop_find(DeviceState *dev, const char *name)
{
977
    ObjectClass *class;
G
Gerd Hoffmann 已提交
978 979 980
    Property *prop;

    /* device properties */
981 982 983 984 985 986 987 988
    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 已提交
989 990 991 992

    return NULL;
}

993 994 995 996 997
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
                                    Property *prop, const char *value)
{
    switch (ret) {
    case -EEXIST:
998
        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
999
                  object_get_typename(OBJECT(dev)), prop->name, value);
1000 1001 1002
        break;
    default:
    case -EINVAL:
1003 1004
        error_setg(errp, QERR_PROPERTY_VALUE_BAD,
                   object_get_typename(OBJECT(dev)), prop->name, value);
1005 1006
        break;
    case -ENOENT:
1007
        error_setg(errp, "Property '%s.%s' can't find value '%s'",
1008
                  object_get_typename(OBJECT(dev)), prop->name, value);
1009 1010 1011 1012 1013 1014
        break;
    case 0:
        break;
    }
}

1015 1016
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
{
1017
    object_property_set_bool(OBJECT(dev), value, name, &error_abort);
1018 1019
}

J
Juan Quintela 已提交
1020 1021
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
{
1022
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
J
Juan Quintela 已提交
1023 1024
}

G
Gerd Hoffmann 已提交
1025 1026
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
{
1027
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
G
Gerd Hoffmann 已提交
1028 1029 1030 1031
}

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

1035 1036
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
{
1037
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
1038 1039
}

B
Blue Swirl 已提交
1040 1041
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
{
1042
    object_property_set_int(OBJECT(dev), value, name, &error_abort);
B
Blue Swirl 已提交
1043 1044
}

1045
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
1046
{
1047
    object_property_set_str(OBJECT(dev), value, name, &error_abort);
1048 1049
}

1050 1051
void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
                           const uint8_t *value)
G
Gerd Hoffmann 已提交
1052
{
P
Paolo Bonzini 已提交
1053 1054 1055 1056
    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]);

1057
    object_property_set_str(OBJECT(dev), str, name, &error_abort);
G
Gerd Hoffmann 已提交
1058 1059
}

P
Paolo Bonzini 已提交
1060
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
1061
{
P
Paolo Bonzini 已提交
1062 1063 1064 1065
    Property *prop;

    prop = qdev_prop_find(dev, name);
    object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1066
                            name, &error_abort);
1067 1068
}

G
Gerd Hoffmann 已提交
1069 1070
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
{
1071 1072 1073 1074 1075 1076 1077
    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 已提交
1078 1079
}

1080
static GList *global_props;
1081

1082
void qdev_prop_register_global(GlobalProperty *prop)
1083
{
1084
    global_props = g_list_append(global_props, prop);
1085 1086
}

1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
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);
}

1101 1102 1103 1104 1105 1106 1107
void register_compat_props_array(GlobalProperty *prop)
{
    for (; prop && prop->driver; prop++) {
        register_compat_prop(prop->driver, prop->property, prop->value);
    }
}

1108
void qdev_prop_register_global_list(GlobalProperty *props)
1109
{
1110
    int i;
1111

1112 1113
    for (i = 0; props[i].driver != NULL; i++) {
        qdev_prop_register_global(props+i);
1114
    }
1115 1116
}

1117
int qdev_prop_check_globals(void)
1118
{
1119
    GList *l;
1120 1121
    int ret = 0;

1122 1123
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
        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) {
            error_report("Warning: global %s.%s has invalid class name",
                       prop->driver, prop->property);
            ret = 1;
            continue;
        }
        dc = DEVICE_CLASS(oc);
        if (!dc->hotpluggable && !prop->used) {
            error_report("Warning: global %s.%s=%s not used",
                       prop->driver, prop->property, prop->value);
            ret = 1;
1145 1146 1147 1148 1149 1150
            continue;
        }
    }
    return ret;
}

1151
static void qdev_prop_set_globals_for_type(DeviceState *dev,
1152
                                           const char *typename)
1153
{
1154
    GList *l;
1155

1156 1157
    for (l = global_props; l; l = l->next) {
        GlobalProperty *prop = l->data;
1158 1159 1160 1161 1162
        Error *err = NULL;

        if (strcmp(typename, prop->driver) != 0) {
            continue;
        }
1163
        prop->used = true;
P
Paolo Bonzini 已提交
1164
        object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
1165
        if (err != NULL) {
1166 1167
            error_prepend(&err, "can't apply global %s.%s=%s: ",
                          prop->driver, prop->property, prop->value);
1168
            if (!dev->hotplugged && prop->errp) {
1169 1170 1171 1172 1173
                error_propagate(prop->errp, err);
            } else {
                assert(prop->user_provided);
                error_reportf_err(err, "Warning: ");
            }
1174 1175 1176 1177
        }
    }
}

1178
void qdev_prop_set_globals(DeviceState *dev)
1179
{
1180 1181 1182
    ObjectClass *class = object_get_class(OBJECT(dev));

    do {
1183
        qdev_prop_set_globals_for_type(dev, object_class_get_name(class));
1184 1185
        class = object_class_get_parent(class);
    } while (class);
1186
}
1187 1188 1189

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

1190 1191
static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1192 1193 1194 1195 1196
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1197
    visit_type_size(v, name, ptr, errp);
1198 1199
}

1200 1201
static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
                     Error **errp)
1202 1203 1204 1205 1206
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);

1207
    visit_type_size(v, name, ptr, errp);
1208 1209 1210 1211 1212 1213
}

PropertyInfo qdev_prop_size = {
    .name  = "size",
    .get = get_size,
    .set = set_size,
1214
    .set_default_value = set_default_value_uint,
1215
};