Merge remote-tracking branch 'remotes/philmd-gitlab/tags/renesas-20201027' into staging
[qemu.git] / hw / core / qdev-properties-system.c
1 /*
2 * qdev property parsing
3 * (parts specific for qemu-system-*)
4 *
5 * This file is based on code from hw/qdev-properties.c from
6 * commit 074a86fccd185616469dfcdc0e157f438aebba18,
7 * Copyright (c) Gerd Hoffmann <kraxel@redhat.com> and other contributors.
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
13 #include "qemu/osdep.h"
14 #include "hw/qdev-properties.h"
15 #include "qapi/error.h"
16 #include "qapi/visitor.h"
17 #include "qapi/qapi-types-block.h"
18 #include "qapi/qapi-types-machine.h"
19 #include "qapi/qapi-types-migration.h"
20 #include "qapi/qmp/qerror.h"
21 #include "qemu/ctype.h"
22 #include "qemu/cutils.h"
23 #include "qemu/units.h"
24 #include "qemu/error-report.h"
25 #include "qdev-prop-internal.h"
26
27 #include "audio/audio.h"
28 #include "chardev/char-fe.h"
29 #include "sysemu/block-backend.h"
30 #include "sysemu/blockdev.h"
31 #include "net/net.h"
32 #include "hw/pci/pci.h"
33 #include "util/block-helpers.h"
34
35 static bool check_prop_still_unset(DeviceState *dev, const char *name,
36 const void *old_val, const char *new_val,
37 Error **errp)
38 {
39 const GlobalProperty *prop = qdev_find_global_prop(dev, name);
40
41 if (!old_val) {
42 return true;
43 }
44
45 if (prop) {
46 error_setg(errp, "-global %s.%s=... conflicts with %s=%s",
47 prop->driver, prop->property, name, new_val);
48 } else {
49 /* Error message is vague, but a better one would be hard */
50 error_setg(errp, "%s=%s conflicts, and override is not implemented",
51 name, new_val);
52 }
53 return false;
54 }
55
56
57 /* --- drive --- */
58
59 static void get_drive(Object *obj, Visitor *v, const char *name, void *opaque,
60 Error **errp)
61 {
62 DeviceState *dev = DEVICE(obj);
63 Property *prop = opaque;
64 void **ptr = qdev_get_prop_ptr(dev, prop);
65 const char *value;
66 char *p;
67
68 if (*ptr) {
69 value = blk_name(*ptr);
70 if (!*value) {
71 BlockDriverState *bs = blk_bs(*ptr);
72 if (bs) {
73 value = bdrv_get_node_name(bs);
74 }
75 }
76 } else {
77 value = "";
78 }
79
80 p = g_strdup(value);
81 visit_type_str(v, name, &p, errp);
82 g_free(p);
83 }
84
85 static void set_drive_helper(Object *obj, Visitor *v, const char *name,
86 void *opaque, bool iothread, Error **errp)
87 {
88 DeviceState *dev = DEVICE(obj);
89 Property *prop = opaque;
90 void **ptr = qdev_get_prop_ptr(dev, prop);
91 char *str;
92 BlockBackend *blk;
93 bool blk_created = false;
94 int ret;
95
96 if (dev->realized) {
97 qdev_prop_set_after_realize(dev, name, errp);
98 return;
99 }
100
101 if (!visit_type_str(v, name, &str, errp)) {
102 return;
103 }
104
105 /*
106 * TODO Should this really be an error? If no, the old value
107 * needs to be released before we store the new one.
108 */
109 if (!check_prop_still_unset(dev, name, *ptr, str, errp)) {
110 return;
111 }
112
113 if (!*str) {
114 g_free(str);
115 *ptr = NULL;
116 return;
117 }
118
119 blk = blk_by_name(str);
120 if (!blk) {
121 BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
122 if (bs) {
123 /*
124 * If the device supports iothreads, it will make sure to move the
125 * block node to the right AioContext if necessary (or fail if this
126 * isn't possible because of other users). Devices that are not
127 * aware of iothreads require their BlockBackends to be in the main
128 * AioContext.
129 */
130 AioContext *ctx = iothread ? bdrv_get_aio_context(bs) :
131 qemu_get_aio_context();
132 blk = blk_new(ctx, 0, BLK_PERM_ALL);
133 blk_created = true;
134
135 ret = blk_insert_bs(blk, bs, errp);
136 if (ret < 0) {
137 goto fail;
138 }
139 }
140 }
141 if (!blk) {
142 error_setg(errp, "Property '%s.%s' can't find value '%s'",
143 object_get_typename(OBJECT(dev)), prop->name, str);
144 goto fail;
145 }
146 if (blk_attach_dev(blk, dev) < 0) {
147 DriveInfo *dinfo = blk_legacy_dinfo(blk);
148
149 if (dinfo && dinfo->type != IF_NONE) {
150 error_setg(errp, "Drive '%s' is already in use because "
151 "it has been automatically connected to another "
152 "device (did you need 'if=none' in the drive options?)",
153 str);
154 } else {
155 error_setg(errp, "Drive '%s' is already in use by another device",
156 str);
157 }
158 goto fail;
159 }
160
161 *ptr = blk;
162
163 fail:
164 if (blk_created) {
165 /* If we need to keep a reference, blk_attach_dev() took it */
166 blk_unref(blk);
167 }
168
169 g_free(str);
170 }
171
172 static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
173 Error **errp)
174 {
175 set_drive_helper(obj, v, name, opaque, false, errp);
176 }
177
178 static void set_drive_iothread(Object *obj, Visitor *v, const char *name,
179 void *opaque, Error **errp)
180 {
181 set_drive_helper(obj, v, name, opaque, true, errp);
182 }
183
184 static void release_drive(Object *obj, const char *name, void *opaque)
185 {
186 DeviceState *dev = DEVICE(obj);
187 Property *prop = opaque;
188 BlockBackend **ptr = qdev_get_prop_ptr(dev, prop);
189
190 if (*ptr) {
191 AioContext *ctx = blk_get_aio_context(*ptr);
192
193 aio_context_acquire(ctx);
194 blockdev_auto_del(*ptr);
195 blk_detach_dev(*ptr, dev);
196 aio_context_release(ctx);
197 }
198 }
199
200 const PropertyInfo qdev_prop_drive = {
201 .name = "str",
202 .description = "Node name or ID of a block device to use as a backend",
203 .get = get_drive,
204 .set = set_drive,
205 .release = release_drive,
206 };
207
208 const PropertyInfo qdev_prop_drive_iothread = {
209 .name = "str",
210 .description = "Node name or ID of a block device to use as a backend",
211 .get = get_drive,
212 .set = set_drive_iothread,
213 .release = release_drive,
214 };
215
216 /* --- character device --- */
217
218 static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,
219 Error **errp)
220 {
221 DeviceState *dev = DEVICE(obj);
222 CharBackend *be = qdev_get_prop_ptr(dev, opaque);
223 char *p;
224
225 p = g_strdup(be->chr && be->chr->label ? be->chr->label : "");
226 visit_type_str(v, name, &p, errp);
227 g_free(p);
228 }
229
230 static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
231 Error **errp)
232 {
233 DeviceState *dev = DEVICE(obj);
234 Property *prop = opaque;
235 CharBackend *be = qdev_get_prop_ptr(dev, prop);
236 Chardev *s;
237 char *str;
238
239 if (dev->realized) {
240 qdev_prop_set_after_realize(dev, name, errp);
241 return;
242 }
243
244 if (!visit_type_str(v, name, &str, errp)) {
245 return;
246 }
247
248 /*
249 * TODO Should this really be an error? If no, the old value
250 * needs to be released before we store the new one.
251 */
252 if (!check_prop_still_unset(dev, name, be->chr, str, errp)) {
253 return;
254 }
255
256 if (!*str) {
257 g_free(str);
258 be->chr = NULL;
259 return;
260 }
261
262 s = qemu_chr_find(str);
263 if (s == NULL) {
264 error_setg(errp, "Property '%s.%s' can't find value '%s'",
265 object_get_typename(obj), prop->name, str);
266 } else if (!qemu_chr_fe_init(be, s, errp)) {
267 error_prepend(errp, "Property '%s.%s' can't take value '%s': ",
268 object_get_typename(obj), prop->name, str);
269 }
270 g_free(str);
271 }
272
273 static void release_chr(Object *obj, const char *name, void *opaque)
274 {
275 DeviceState *dev = DEVICE(obj);
276 Property *prop = opaque;
277 CharBackend *be = qdev_get_prop_ptr(dev, prop);
278
279 qemu_chr_fe_deinit(be, false);
280 }
281
282 const PropertyInfo qdev_prop_chr = {
283 .name = "str",
284 .description = "ID of a chardev to use as a backend",
285 .get = get_chr,
286 .set = set_chr,
287 .release = release_chr,
288 };
289
290 /* --- mac address --- */
291
292 /*
293 * accepted syntax versions:
294 * 01:02:03:04:05:06
295 * 01-02-03-04-05-06
296 */
297 static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
298 Error **errp)
299 {
300 DeviceState *dev = DEVICE(obj);
301 Property *prop = opaque;
302 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
303 char buffer[2 * 6 + 5 + 1];
304 char *p = buffer;
305
306 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
307 mac->a[0], mac->a[1], mac->a[2],
308 mac->a[3], mac->a[4], mac->a[5]);
309
310 visit_type_str(v, name, &p, errp);
311 }
312
313 static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
314 Error **errp)
315 {
316 DeviceState *dev = DEVICE(obj);
317 Property *prop = opaque;
318 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
319 int i, pos;
320 char *str;
321 const char *p;
322
323 if (dev->realized) {
324 qdev_prop_set_after_realize(dev, name, errp);
325 return;
326 }
327
328 if (!visit_type_str(v, name, &str, errp)) {
329 return;
330 }
331
332 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
333 long val;
334
335 if (!qemu_isxdigit(str[pos])) {
336 goto inval;
337 }
338 if (!qemu_isxdigit(str[pos + 1])) {
339 goto inval;
340 }
341 if (i == 5) {
342 if (str[pos + 2] != '\0') {
343 goto inval;
344 }
345 } else {
346 if (str[pos + 2] != ':' && str[pos + 2] != '-') {
347 goto inval;
348 }
349 }
350 if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) {
351 goto inval;
352 }
353 mac->a[i] = val;
354 }
355 g_free(str);
356 return;
357
358 inval:
359 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
360 g_free(str);
361 }
362
363 const PropertyInfo qdev_prop_macaddr = {
364 .name = "str",
365 .description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
366 .get = get_mac,
367 .set = set_mac,
368 };
369
370 void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
371 const uint8_t *value)
372 {
373 char str[2 * 6 + 5 + 1];
374 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
375 value[0], value[1], value[2], value[3], value[4], value[5]);
376
377 object_property_set_str(OBJECT(dev), name, str, &error_abort);
378 }
379
380 /* --- netdev device --- */
381 static void get_netdev(Object *obj, Visitor *v, const char *name,
382 void *opaque, Error **errp)
383 {
384 DeviceState *dev = DEVICE(obj);
385 Property *prop = opaque;
386 NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
387 char *p = g_strdup(peers_ptr->ncs[0] ? peers_ptr->ncs[0]->name : "");
388
389 visit_type_str(v, name, &p, errp);
390 g_free(p);
391 }
392
393 static void set_netdev(Object *obj, Visitor *v, const char *name,
394 void *opaque, Error **errp)
395 {
396 DeviceState *dev = DEVICE(obj);
397 Property *prop = opaque;
398 NICPeers *peers_ptr = qdev_get_prop_ptr(dev, prop);
399 NetClientState **ncs = peers_ptr->ncs;
400 NetClientState *peers[MAX_QUEUE_NUM];
401 int queues, err = 0, i = 0;
402 char *str;
403
404 if (dev->realized) {
405 qdev_prop_set_after_realize(dev, name, errp);
406 return;
407 }
408
409 if (!visit_type_str(v, name, &str, errp)) {
410 return;
411 }
412
413 queues = qemu_find_net_clients_except(str, peers,
414 NET_CLIENT_DRIVER_NIC,
415 MAX_QUEUE_NUM);
416 if (queues == 0) {
417 err = -ENOENT;
418 goto out;
419 }
420
421 if (queues > MAX_QUEUE_NUM) {
422 error_setg(errp, "queues of backend '%s'(%d) exceeds QEMU limitation(%d)",
423 str, queues, MAX_QUEUE_NUM);
424 goto out;
425 }
426
427 for (i = 0; i < queues; i++) {
428 if (peers[i]->peer) {
429 err = -EEXIST;
430 goto out;
431 }
432
433 /*
434 * TODO Should this really be an error? If no, the old value
435 * needs to be released before we store the new one.
436 */
437 if (!check_prop_still_unset(dev, name, ncs[i], str, errp)) {
438 goto out;
439 }
440
441 ncs[i] = peers[i];
442 ncs[i]->queue_index = i;
443 }
444
445 peers_ptr->queues = queues;
446
447 out:
448 error_set_from_qdev_prop_error(errp, err, dev, prop, str);
449 g_free(str);
450 }
451
452 const PropertyInfo qdev_prop_netdev = {
453 .name = "str",
454 .description = "ID of a netdev to use as a backend",
455 .get = get_netdev,
456 .set = set_netdev,
457 };
458
459
460 /* --- audiodev --- */
461 static void get_audiodev(Object *obj, Visitor *v, const char* name,
462 void *opaque, Error **errp)
463 {
464 DeviceState *dev = DEVICE(obj);
465 Property *prop = opaque;
466 QEMUSoundCard *card = qdev_get_prop_ptr(dev, prop);
467 char *p = g_strdup(audio_get_id(card));
468
469 visit_type_str(v, name, &p, errp);
470 g_free(p);
471 }
472
473 static void set_audiodev(Object *obj, Visitor *v, const char* name,
474 void *opaque, Error **errp)
475 {
476 DeviceState *dev = DEVICE(obj);
477 Property *prop = opaque;
478 QEMUSoundCard *card = qdev_get_prop_ptr(dev, prop);
479 AudioState *state;
480 int err = 0;
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
492 state = audio_state_by_name(str);
493
494 if (!state) {
495 err = -ENOENT;
496 goto out;
497 }
498 card->state = state;
499
500 out:
501 error_set_from_qdev_prop_error(errp, err, dev, prop, str);
502 g_free(str);
503 }
504
505 const PropertyInfo qdev_prop_audiodev = {
506 .name = "str",
507 .description = "ID of an audiodev to use as a backend",
508 /* release done on shutdown */
509 .get = get_audiodev,
510 .set = set_audiodev,
511 };
512
513 bool qdev_prop_set_drive_err(DeviceState *dev, const char *name,
514 BlockBackend *value, Error **errp)
515 {
516 const char *ref = "";
517
518 if (value) {
519 ref = blk_name(value);
520 if (!*ref) {
521 const BlockDriverState *bs = blk_bs(value);
522 if (bs) {
523 ref = bdrv_get_node_name(bs);
524 }
525 }
526 }
527
528 return object_property_set_str(OBJECT(dev), name, ref, errp);
529 }
530
531 void qdev_prop_set_drive(DeviceState *dev, const char *name,
532 BlockBackend *value)
533 {
534 qdev_prop_set_drive_err(dev, name, value, &error_abort);
535 }
536
537 void qdev_prop_set_chr(DeviceState *dev, const char *name,
538 Chardev *value)
539 {
540 assert(!value || value->label);
541 object_property_set_str(OBJECT(dev), name, value ? value->label : "",
542 &error_abort);
543 }
544
545 void qdev_prop_set_netdev(DeviceState *dev, const char *name,
546 NetClientState *value)
547 {
548 assert(!value || value->name);
549 object_property_set_str(OBJECT(dev), name, value ? value->name : "",
550 &error_abort);
551 }
552
553 void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
554 {
555 qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
556 if (nd->netdev) {
557 qdev_prop_set_netdev(dev, "netdev", nd->netdev);
558 }
559 if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
560 object_property_find(OBJECT(dev), "vectors")) {
561 qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
562 }
563 nd->instantiated = 1;
564 }
565
566 /* --- lost tick policy --- */
567
568 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
569
570 const PropertyInfo qdev_prop_losttickpolicy = {
571 .name = "LostTickPolicy",
572 .enum_table = &LostTickPolicy_lookup,
573 .get = qdev_propinfo_get_enum,
574 .set = qdev_propinfo_set_enum,
575 .set_default_value = qdev_propinfo_set_default_value_enum,
576 };
577
578 /* --- blocksize --- */
579
580 static void set_blocksize(Object *obj, Visitor *v, const char *name,
581 void *opaque, Error **errp)
582 {
583 DeviceState *dev = DEVICE(obj);
584 Property *prop = opaque;
585 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
586 uint64_t value;
587 Error *local_err = NULL;
588
589 if (dev->realized) {
590 qdev_prop_set_after_realize(dev, name, errp);
591 return;
592 }
593
594 if (!visit_type_size(v, name, &value, errp)) {
595 return;
596 }
597 check_block_size(dev->id ? : "", name, value, &local_err);
598 if (local_err) {
599 error_propagate(errp, local_err);
600 return;
601 }
602 *ptr = value;
603 }
604
605 const PropertyInfo qdev_prop_blocksize = {
606 .name = "size",
607 .description = "A power of two between " MIN_BLOCK_SIZE_STR
608 " and " MAX_BLOCK_SIZE_STR,
609 .get = qdev_propinfo_get_size32,
610 .set = set_blocksize,
611 .set_default_value = qdev_propinfo_set_default_value_uint,
612 };
613
614 /* --- Block device error handling policy --- */
615
616 QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
617
618 const PropertyInfo qdev_prop_blockdev_on_error = {
619 .name = "BlockdevOnError",
620 .description = "Error handling policy, "
621 "report/ignore/enospc/stop/auto",
622 .enum_table = &BlockdevOnError_lookup,
623 .get = qdev_propinfo_get_enum,
624 .set = qdev_propinfo_set_enum,
625 .set_default_value = qdev_propinfo_set_default_value_enum,
626 };
627
628 /* --- BIOS CHS translation */
629
630 QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
631
632 const PropertyInfo qdev_prop_bios_chs_trans = {
633 .name = "BiosAtaTranslation",
634 .description = "Logical CHS translation algorithm, "
635 "auto/none/lba/large/rechs",
636 .enum_table = &BiosAtaTranslation_lookup,
637 .get = qdev_propinfo_get_enum,
638 .set = qdev_propinfo_set_enum,
639 .set_default_value = qdev_propinfo_set_default_value_enum,
640 };
641
642 /* --- FDC default drive types */
643
644 const PropertyInfo qdev_prop_fdc_drive_type = {
645 .name = "FdcDriveType",
646 .description = "FDC drive type, "
647 "144/288/120/none/auto",
648 .enum_table = &FloppyDriveType_lookup,
649 .get = qdev_propinfo_get_enum,
650 .set = qdev_propinfo_set_enum,
651 .set_default_value = qdev_propinfo_set_default_value_enum,
652 };
653
654 /* --- MultiFDCompression --- */
655
656 const PropertyInfo qdev_prop_multifd_compression = {
657 .name = "MultiFDCompression",
658 .description = "multifd_compression values, "
659 "none/zlib/zstd",
660 .enum_table = &MultiFDCompression_lookup,
661 .get = qdev_propinfo_get_enum,
662 .set = qdev_propinfo_set_enum,
663 .set_default_value = qdev_propinfo_set_default_value_enum,
664 };
665
666 /* --- Reserved Region --- */
667
668 /*
669 * Accepted syntax:
670 * <low address>:<high address>:<type>
671 * where low/high addresses are uint64_t in hexadecimal
672 * and type is a non-negative decimal integer
673 */
674 static void get_reserved_region(Object *obj, Visitor *v, const char *name,
675 void *opaque, Error **errp)
676 {
677 DeviceState *dev = DEVICE(obj);
678 Property *prop = opaque;
679 ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
680 char buffer[64];
681 char *p = buffer;
682 int rc;
683
684 rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u",
685 rr->low, rr->high, rr->type);
686 assert(rc < sizeof(buffer));
687
688 visit_type_str(v, name, &p, errp);
689 }
690
691 static void set_reserved_region(Object *obj, Visitor *v, const char *name,
692 void *opaque, Error **errp)
693 {
694 DeviceState *dev = DEVICE(obj);
695 Property *prop = opaque;
696 ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
697 Error *local_err = NULL;
698 const char *endptr;
699 char *str;
700 int ret;
701
702 if (dev->realized) {
703 qdev_prop_set_after_realize(dev, name, errp);
704 return;
705 }
706
707 visit_type_str(v, name, &str, &local_err);
708 if (local_err) {
709 error_propagate(errp, local_err);
710 return;
711 }
712
713 ret = qemu_strtou64(str, &endptr, 16, &rr->low);
714 if (ret) {
715 error_setg(errp, "start address of '%s'"
716 " must be a hexadecimal integer", name);
717 goto out;
718 }
719 if (*endptr != ':') {
720 goto separator_error;
721 }
722
723 ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high);
724 if (ret) {
725 error_setg(errp, "end address of '%s'"
726 " must be a hexadecimal integer", name);
727 goto out;
728 }
729 if (*endptr != ':') {
730 goto separator_error;
731 }
732
733 ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type);
734 if (ret) {
735 error_setg(errp, "type of '%s'"
736 " must be a non-negative decimal integer", name);
737 }
738 goto out;
739
740 separator_error:
741 error_setg(errp, "reserved region fields must be separated with ':'");
742 out:
743 g_free(str);
744 return;
745 }
746
747 const PropertyInfo qdev_prop_reserved_region = {
748 .name = "reserved_region",
749 .description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0",
750 .get = get_reserved_region,
751 .set = set_reserved_region,
752 };
753
754 /* --- pci address --- */
755
756 /*
757 * bus-local address, i.e. "$slot" or "$slot.$fn"
758 */
759 static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
760 void *opaque, Error **errp)
761 {
762 DeviceState *dev = DEVICE(obj);
763 Property *prop = opaque;
764 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
765 unsigned int slot, fn, n;
766 char *str;
767
768 if (dev->realized) {
769 qdev_prop_set_after_realize(dev, name, errp);
770 return;
771 }
772
773 if (!visit_type_str(v, name, &str, NULL)) {
774 if (!visit_type_int32(v, name, &value, errp)) {
775 return;
776 }
777 if (value < -1 || value > 255) {
778 error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
779 name ? name : "null", "pci_devfn");
780 return;
781 }
782 *ptr = value;
783 return;
784 }
785
786 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
787 fn = 0;
788 if (sscanf(str, "%x%n", &slot, &n) != 1) {
789 goto invalid;
790 }
791 }
792 if (str[n] != '\0' || fn > 7 || slot > 31) {
793 goto invalid;
794 }
795 *ptr = slot << 3 | fn;
796 g_free(str);
797 return;
798
799 invalid:
800 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
801 g_free(str);
802 }
803
804 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
805 size_t len)
806 {
807 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
808
809 if (*ptr == -1) {
810 return snprintf(dest, len, "<unset>");
811 } else {
812 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
813 }
814 }
815
816 const PropertyInfo qdev_prop_pci_devfn = {
817 .name = "int32",
818 .description = "Slot and optional function number, example: 06.0 or 06",
819 .print = print_pci_devfn,
820 .get = qdev_propinfo_get_int32,
821 .set = set_pci_devfn,
822 .set_default_value = qdev_propinfo_set_default_value_int,
823 };
824
825 /* --- pci host address --- */
826
827 static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
828 void *opaque, Error **errp)
829 {
830 DeviceState *dev = DEVICE(obj);
831 Property *prop = opaque;
832 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
833 char buffer[] = "ffff:ff:ff.f";
834 char *p = buffer;
835 int rc = 0;
836
837 /*
838 * Catch "invalid" device reference from vfio-pci and allow the
839 * default buffer representing the non-existent device to be used.
840 */
841 if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
842 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
843 addr->domain, addr->bus, addr->slot, addr->function);
844 assert(rc == sizeof(buffer) - 1);
845 }
846
847 visit_type_str(v, name, &p, errp);
848 }
849
850 /*
851 * Parse [<domain>:]<bus>:<slot>.<func>
852 * if <domain> is not supplied, it's assumed to be 0.
853 */
854 static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
855 void *opaque, Error **errp)
856 {
857 DeviceState *dev = DEVICE(obj);
858 Property *prop = opaque;
859 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
860 char *str, *p;
861 const char *e;
862 unsigned long val;
863 unsigned long dom = 0, bus = 0;
864 unsigned int slot = 0, func = 0;
865
866 if (dev->realized) {
867 qdev_prop_set_after_realize(dev, name, errp);
868 return;
869 }
870
871 if (!visit_type_str(v, name, &str, errp)) {
872 return;
873 }
874
875 p = str;
876 if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0xffff || e == p) {
877 goto inval;
878 }
879 if (*e != ':') {
880 goto inval;
881 }
882 bus = val;
883
884 p = (char *)e + 1;
885 if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) {
886 goto inval;
887 }
888 if (*e == ':') {
889 dom = bus;
890 bus = val;
891 p = (char *)e + 1;
892 if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) {
893 goto inval;
894 }
895 }
896 slot = val;
897
898 if (*e != '.') {
899 goto inval;
900 }
901 p = (char *)e + 1;
902 if (qemu_strtoul(p, &e, 10, &val) < 0 || val > 7 || e == p) {
903 goto inval;
904 }
905 func = val;
906
907 if (bus > 0xff) {
908 goto inval;
909 }
910
911 if (*e) {
912 goto inval;
913 }
914
915 addr->domain = dom;
916 addr->bus = bus;
917 addr->slot = slot;
918 addr->function = func;
919
920 g_free(str);
921 return;
922
923 inval:
924 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
925 g_free(str);
926 }
927
928 const PropertyInfo qdev_prop_pci_host_devaddr = {
929 .name = "str",
930 .description = "Address (bus/device/function) of "
931 "the host device, example: 04:10.0",
932 .get = get_pci_host_devaddr,
933 .set = set_pci_host_devaddr,
934 };
935
936 /* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
937
938 const PropertyInfo qdev_prop_off_auto_pcibar = {
939 .name = "OffAutoPCIBAR",
940 .description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
941 .enum_table = &OffAutoPCIBAR_lookup,
942 .get = qdev_propinfo_get_enum,
943 .set = qdev_propinfo_set_enum,
944 .set_default_value = qdev_propinfo_set_default_value_enum,
945 };
946
947 /* --- PCIELinkSpeed 2_5/5/8/16 -- */
948
949 static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
950 void *opaque, Error **errp)
951 {
952 DeviceState *dev = DEVICE(obj);
953 Property *prop = opaque;
954 PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
955 int speed;
956
957 switch (*p) {
958 case QEMU_PCI_EXP_LNK_2_5GT:
959 speed = PCIE_LINK_SPEED_2_5;
960 break;
961 case QEMU_PCI_EXP_LNK_5GT:
962 speed = PCIE_LINK_SPEED_5;
963 break;
964 case QEMU_PCI_EXP_LNK_8GT:
965 speed = PCIE_LINK_SPEED_8;
966 break;
967 case QEMU_PCI_EXP_LNK_16GT:
968 speed = PCIE_LINK_SPEED_16;
969 break;
970 default:
971 /* Unreachable */
972 abort();
973 }
974
975 visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp);
976 }
977
978 static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
979 void *opaque, Error **errp)
980 {
981 DeviceState *dev = DEVICE(obj);
982 Property *prop = opaque;
983 PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
984 int speed;
985
986 if (dev->realized) {
987 qdev_prop_set_after_realize(dev, name, errp);
988 return;
989 }
990
991 if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table,
992 errp)) {
993 return;
994 }
995
996 switch (speed) {
997 case PCIE_LINK_SPEED_2_5:
998 *p = QEMU_PCI_EXP_LNK_2_5GT;
999 break;
1000 case PCIE_LINK_SPEED_5:
1001 *p = QEMU_PCI_EXP_LNK_5GT;
1002 break;
1003 case PCIE_LINK_SPEED_8:
1004 *p = QEMU_PCI_EXP_LNK_8GT;
1005 break;
1006 case PCIE_LINK_SPEED_16:
1007 *p = QEMU_PCI_EXP_LNK_16GT;
1008 break;
1009 default:
1010 /* Unreachable */
1011 abort();
1012 }
1013 }
1014
1015 const PropertyInfo qdev_prop_pcie_link_speed = {
1016 .name = "PCIELinkSpeed",
1017 .description = "2_5/5/8/16",
1018 .enum_table = &PCIELinkSpeed_lookup,
1019 .get = get_prop_pcielinkspeed,
1020 .set = set_prop_pcielinkspeed,
1021 .set_default_value = qdev_propinfo_set_default_value_enum,
1022 };
1023
1024 /* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */
1025
1026 static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
1027 void *opaque, Error **errp)
1028 {
1029 DeviceState *dev = DEVICE(obj);
1030 Property *prop = opaque;
1031 PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
1032 int width;
1033
1034 switch (*p) {
1035 case QEMU_PCI_EXP_LNK_X1:
1036 width = PCIE_LINK_WIDTH_1;
1037 break;
1038 case QEMU_PCI_EXP_LNK_X2:
1039 width = PCIE_LINK_WIDTH_2;
1040 break;
1041 case QEMU_PCI_EXP_LNK_X4:
1042 width = PCIE_LINK_WIDTH_4;
1043 break;
1044 case QEMU_PCI_EXP_LNK_X8:
1045 width = PCIE_LINK_WIDTH_8;
1046 break;
1047 case QEMU_PCI_EXP_LNK_X12:
1048 width = PCIE_LINK_WIDTH_12;
1049 break;
1050 case QEMU_PCI_EXP_LNK_X16:
1051 width = PCIE_LINK_WIDTH_16;
1052 break;
1053 case QEMU_PCI_EXP_LNK_X32:
1054 width = PCIE_LINK_WIDTH_32;
1055 break;
1056 default:
1057 /* Unreachable */
1058 abort();
1059 }
1060
1061 visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp);
1062 }
1063
1064 static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
1065 void *opaque, Error **errp)
1066 {
1067 DeviceState *dev = DEVICE(obj);
1068 Property *prop = opaque;
1069 PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
1070 int width;
1071
1072 if (dev->realized) {
1073 qdev_prop_set_after_realize(dev, name, errp);
1074 return;
1075 }
1076
1077 if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table,
1078 errp)) {
1079 return;
1080 }
1081
1082 switch (width) {
1083 case PCIE_LINK_WIDTH_1:
1084 *p = QEMU_PCI_EXP_LNK_X1;
1085 break;
1086 case PCIE_LINK_WIDTH_2:
1087 *p = QEMU_PCI_EXP_LNK_X2;
1088 break;
1089 case PCIE_LINK_WIDTH_4:
1090 *p = QEMU_PCI_EXP_LNK_X4;
1091 break;
1092 case PCIE_LINK_WIDTH_8:
1093 *p = QEMU_PCI_EXP_LNK_X8;
1094 break;
1095 case PCIE_LINK_WIDTH_12:
1096 *p = QEMU_PCI_EXP_LNK_X12;
1097 break;
1098 case PCIE_LINK_WIDTH_16:
1099 *p = QEMU_PCI_EXP_LNK_X16;
1100 break;
1101 case PCIE_LINK_WIDTH_32:
1102 *p = QEMU_PCI_EXP_LNK_X32;
1103 break;
1104 default:
1105 /* Unreachable */
1106 abort();
1107 }
1108 }
1109
1110 const PropertyInfo qdev_prop_pcie_link_width = {
1111 .name = "PCIELinkWidth",
1112 .description = "1/2/4/8/12/16/32",
1113 .enum_table = &PCIELinkWidth_lookup,
1114 .get = get_prop_pcielinkwidth,
1115 .set = set_prop_pcielinkwidth,
1116 .set_default_value = qdev_propinfo_set_default_value_enum,
1117 };