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