1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "qapi/error.h"
15#include "qapi/qmp/qnull.h"
16#include "cpu.h"
17#include "qemu/cutils.h"
18#include "hw/ppc/spapr_drc.h"
19#include "qom/object.h"
20#include "hw/qdev.h"
21#include "qapi/visitor.h"
22#include "qemu/error-report.h"
23#include "hw/ppc/spapr.h"
24#include "hw/pci-host/spapr.h"
25#include "sysemu/device_tree.h"
26#include "trace.h"
27
28#define DRC_CONTAINER_PATH "/dr-connector"
29#define DRC_INDEX_TYPE_SHIFT 28
30#define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1)
31
32SpaprDrcType spapr_drc_type(SpaprDrc *drc)
33{
34 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
35
36 return 1 << drck->typeshift;
37}
38
39uint32_t spapr_drc_index(SpaprDrc *drc)
40{
41 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
42
43
44
45
46
47 return (drck->typeshift << DRC_INDEX_TYPE_SHIFT)
48 | (drc->id & DRC_INDEX_ID_MASK);
49}
50
51static uint32_t drc_isolate_physical(SpaprDrc *drc)
52{
53 switch (drc->state) {
54 case SPAPR_DRC_STATE_PHYSICAL_POWERON:
55 return RTAS_OUT_SUCCESS;
56 case SPAPR_DRC_STATE_PHYSICAL_CONFIGURED:
57 break;
58 case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
59 return RTAS_OUT_PARAM_ERROR;
60 default:
61 g_assert_not_reached();
62 }
63
64 drc->state = SPAPR_DRC_STATE_PHYSICAL_POWERON;
65
66 if (drc->unplug_requested) {
67 uint32_t drc_index = spapr_drc_index(drc);
68 trace_spapr_drc_set_isolation_state_finalizing(drc_index);
69 spapr_drc_detach(drc);
70 }
71
72 return RTAS_OUT_SUCCESS;
73}
74
75static uint32_t drc_unisolate_physical(SpaprDrc *drc)
76{
77 switch (drc->state) {
78 case SPAPR_DRC_STATE_PHYSICAL_UNISOLATE:
79 case SPAPR_DRC_STATE_PHYSICAL_CONFIGURED:
80 return RTAS_OUT_SUCCESS;
81 case SPAPR_DRC_STATE_PHYSICAL_POWERON:
82 break;
83 default:
84 g_assert_not_reached();
85 }
86
87
88
89
90
91 if (!drc->dev) {
92 return RTAS_OUT_NO_SUCH_INDICATOR;
93 }
94
95 drc->state = SPAPR_DRC_STATE_PHYSICAL_UNISOLATE;
96 drc->ccs_offset = drc->fdt_start_offset;
97 drc->ccs_depth = 0;
98
99 return RTAS_OUT_SUCCESS;
100}
101
102static uint32_t drc_isolate_logical(SpaprDrc *drc)
103{
104 switch (drc->state) {
105 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
106 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
107 return RTAS_OUT_SUCCESS;
108 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
109 break;
110 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
111 return RTAS_OUT_PARAM_ERROR;
112 default:
113 g_assert_not_reached();
114 }
115
116
117
118
119
120
121
122
123
124
125
126 if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB
127 && !drc->unplug_requested) {
128 return RTAS_OUT_HW_ERROR;
129 }
130
131 drc->state = SPAPR_DRC_STATE_LOGICAL_AVAILABLE;
132
133
134
135
136
137
138
139
140
141 if (drc->unplug_requested) {
142 uint32_t drc_index = spapr_drc_index(drc);
143 trace_spapr_drc_set_isolation_state_finalizing(drc_index);
144 spapr_drc_detach(drc);
145 }
146 return RTAS_OUT_SUCCESS;
147}
148
149static uint32_t drc_unisolate_logical(SpaprDrc *drc)
150{
151 switch (drc->state) {
152 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
153 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
154 return RTAS_OUT_SUCCESS;
155 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
156 break;
157 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
158 return RTAS_OUT_NO_SUCH_INDICATOR;
159 default:
160 g_assert_not_reached();
161 }
162
163
164 g_assert(drc->dev);
165
166 drc->state = SPAPR_DRC_STATE_LOGICAL_UNISOLATE;
167 drc->ccs_offset = drc->fdt_start_offset;
168 drc->ccs_depth = 0;
169
170 return RTAS_OUT_SUCCESS;
171}
172
173static uint32_t drc_set_usable(SpaprDrc *drc)
174{
175 switch (drc->state) {
176 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
177 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
178 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
179 return RTAS_OUT_SUCCESS;
180 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
181 break;
182 default:
183 g_assert_not_reached();
184 }
185
186
187
188
189
190
191 if (!drc->dev) {
192 return RTAS_OUT_NO_SUCH_INDICATOR;
193 }
194 if (drc->unplug_requested) {
195
196
197 return RTAS_OUT_NO_SUCH_INDICATOR;
198 }
199
200 drc->state = SPAPR_DRC_STATE_LOGICAL_AVAILABLE;
201
202 return RTAS_OUT_SUCCESS;
203}
204
205static uint32_t drc_set_unusable(SpaprDrc *drc)
206{
207 switch (drc->state) {
208 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
209 return RTAS_OUT_SUCCESS;
210 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
211 break;
212 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
213 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
214 return RTAS_OUT_NO_SUCH_INDICATOR;
215 default:
216 g_assert_not_reached();
217 }
218
219 drc->state = SPAPR_DRC_STATE_LOGICAL_UNUSABLE;
220 if (drc->unplug_requested) {
221 uint32_t drc_index = spapr_drc_index(drc);
222 trace_spapr_drc_set_allocation_state_finalizing(drc_index);
223 spapr_drc_detach(drc);
224 }
225
226 return RTAS_OUT_SUCCESS;
227}
228
229static const char *spapr_drc_name(SpaprDrc *drc)
230{
231 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254 return g_strdup_printf("%s%d", drck->drc_name_prefix, drc->id);
255}
256
257
258
259
260
261
262
263
264static SpaprDREntitySense physical_entity_sense(SpaprDrc *drc)
265{
266
267
268
269
270
271 return drc->dev ? SPAPR_DR_ENTITY_SENSE_PRESENT
272 : SPAPR_DR_ENTITY_SENSE_EMPTY;
273}
274
275static SpaprDREntitySense logical_entity_sense(SpaprDrc *drc)
276{
277 switch (drc->state) {
278 case SPAPR_DRC_STATE_LOGICAL_UNUSABLE:
279 return SPAPR_DR_ENTITY_SENSE_UNUSABLE;
280 case SPAPR_DRC_STATE_LOGICAL_AVAILABLE:
281 case SPAPR_DRC_STATE_LOGICAL_UNISOLATE:
282 case SPAPR_DRC_STATE_LOGICAL_CONFIGURED:
283 g_assert(drc->dev);
284 return SPAPR_DR_ENTITY_SENSE_PRESENT;
285 default:
286 g_assert_not_reached();
287 }
288}
289
290static void prop_get_index(Object *obj, Visitor *v, const char *name,
291 void *opaque, Error **errp)
292{
293 SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj);
294 uint32_t value = spapr_drc_index(drc);
295 visit_type_uint32(v, name, &value, errp);
296}
297
298static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
299 void *opaque, Error **errp)
300{
301 SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj);
302 QNull *null = NULL;
303 Error *err = NULL;
304 int fdt_offset_next, fdt_offset, fdt_depth;
305 void *fdt;
306
307 if (!drc->fdt) {
308 visit_type_null(v, NULL, &null, errp);
309 qobject_unref(null);
310 return;
311 }
312
313 fdt = drc->fdt;
314 fdt_offset = drc->fdt_start_offset;
315 fdt_depth = 0;
316
317 do {
318 const char *name = NULL;
319 const struct fdt_property *prop = NULL;
320 int prop_len = 0, name_len = 0;
321 uint32_t tag;
322
323 tag = fdt_next_tag(fdt, fdt_offset, &fdt_offset_next);
324 switch (tag) {
325 case FDT_BEGIN_NODE:
326 fdt_depth++;
327 name = fdt_get_name(fdt, fdt_offset, &name_len);
328 visit_start_struct(v, name, NULL, 0, &err);
329 if (err) {
330 error_propagate(errp, err);
331 return;
332 }
333 break;
334 case FDT_END_NODE:
335
336 g_assert(fdt_depth > 0);
337 visit_check_struct(v, &err);
338 visit_end_struct(v, NULL);
339 if (err) {
340 error_propagate(errp, err);
341 return;
342 }
343 fdt_depth--;
344 break;
345 case FDT_PROP: {
346 int i;
347 prop = fdt_get_property_by_offset(fdt, fdt_offset, &prop_len);
348 name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
349 visit_start_list(v, name, NULL, 0, &err);
350 if (err) {
351 error_propagate(errp, err);
352 return;
353 }
354 for (i = 0; i < prop_len; i++) {
355 visit_type_uint8(v, NULL, (uint8_t *)&prop->data[i], &err);
356 if (err) {
357 error_propagate(errp, err);
358 return;
359 }
360 }
361 visit_check_list(v, &err);
362 visit_end_list(v, NULL);
363 if (err) {
364 error_propagate(errp, err);
365 return;
366 }
367 break;
368 }
369 default:
370 error_report("device FDT in unexpected state: %d", tag);
371 abort();
372 }
373 fdt_offset = fdt_offset_next;
374 } while (fdt_depth != 0);
375}
376
377void spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp)
378{
379 trace_spapr_drc_attach(spapr_drc_index(drc));
380
381 if (drc->dev) {
382 error_setg(errp, "an attached device is still awaiting release");
383 return;
384 }
385 g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE)
386 || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON));
387
388 drc->dev = d;
389
390 object_property_add_link(OBJECT(drc), "device",
391 object_get_typename(OBJECT(drc->dev)),
392 (Object **)(&drc->dev),
393 NULL, 0, NULL);
394}
395
396static void spapr_drc_release(SpaprDrc *drc)
397{
398 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
399
400 drck->release(drc->dev);
401
402 drc->unplug_requested = false;
403 g_free(drc->fdt);
404 drc->fdt = NULL;
405 drc->fdt_start_offset = 0;
406 object_property_del(OBJECT(drc), "device", &error_abort);
407 drc->dev = NULL;
408}
409
410void spapr_drc_detach(SpaprDrc *drc)
411{
412 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
413
414 trace_spapr_drc_detach(spapr_drc_index(drc));
415
416 g_assert(drc->dev);
417
418 drc->unplug_requested = true;
419
420 if (drc->state != drck->empty_state) {
421 trace_spapr_drc_awaiting_quiesce(spapr_drc_index(drc));
422 return;
423 }
424
425 spapr_drc_release(drc);
426}
427
428void spapr_drc_reset(SpaprDrc *drc)
429{
430 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
431
432 trace_spapr_drc_reset(spapr_drc_index(drc));
433
434
435
436
437 if (drc->unplug_requested) {
438 spapr_drc_release(drc);
439 }
440
441 if (drc->dev) {
442
443 drc->state = drck->ready_state;
444
445
446
447
448 drc->ccs_offset = drc->fdt_start_offset;
449 drc->ccs_depth = 0;
450 } else {
451 drc->state = drck->empty_state;
452 drc->ccs_offset = -1;
453 drc->ccs_depth = -1;
454 }
455}
456
457bool spapr_drc_needed(void *opaque)
458{
459 SpaprDrc *drc = (SpaprDrc *)opaque;
460 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
461
462
463 if (!drc->dev) {
464 return false;
465 }
466
467
468
469
470
471 return (drc->state != drck->ready_state);
472}
473
474static const VMStateDescription vmstate_spapr_drc = {
475 .name = "spapr_drc",
476 .version_id = 1,
477 .minimum_version_id = 1,
478 .needed = spapr_drc_needed,
479 .fields = (VMStateField []) {
480 VMSTATE_UINT32(state, SpaprDrc),
481 VMSTATE_END_OF_LIST()
482 }
483};
484
485static void realize(DeviceState *d, Error **errp)
486{
487 SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
488 Object *root_container;
489 gchar *link_name;
490 gchar *child_name;
491 Error *err = NULL;
492
493 trace_spapr_drc_realize(spapr_drc_index(drc));
494
495
496
497
498
499
500
501 root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
502 link_name = g_strdup_printf("%x", spapr_drc_index(drc));
503 child_name = object_get_canonical_path_component(OBJECT(drc));
504 trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
505 object_property_add_alias(root_container, link_name,
506 drc->owner, child_name, &err);
507 g_free(child_name);
508 g_free(link_name);
509 if (err) {
510 error_propagate(errp, err);
511 return;
512 }
513 vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
514 drc);
515 trace_spapr_drc_realize_complete(spapr_drc_index(drc));
516}
517
518static void unrealize(DeviceState *d, Error **errp)
519{
520 SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
521 Object *root_container;
522 gchar *name;
523
524 trace_spapr_drc_unrealize(spapr_drc_index(drc));
525 vmstate_unregister(DEVICE(drc), &vmstate_spapr_drc, drc);
526 root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
527 name = g_strdup_printf("%x", spapr_drc_index(drc));
528 object_property_del(root_container, name, errp);
529 g_free(name);
530}
531
532SpaprDrc *spapr_dr_connector_new(Object *owner, const char *type,
533 uint32_t id)
534{
535 SpaprDrc *drc = SPAPR_DR_CONNECTOR(object_new(type));
536 char *prop_name;
537
538 drc->id = id;
539 drc->owner = owner;
540 prop_name = g_strdup_printf("dr-connector[%"PRIu32"]",
541 spapr_drc_index(drc));
542 object_property_add_child(owner, prop_name, OBJECT(drc), &error_abort);
543 object_unref(OBJECT(drc));
544 object_property_set_bool(OBJECT(drc), true, "realized", NULL);
545 g_free(prop_name);
546
547 return drc;
548}
549
550static void spapr_dr_connector_instance_init(Object *obj)
551{
552 SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj);
553 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
554
555 object_property_add_uint32_ptr(obj, "id", &drc->id, NULL);
556 object_property_add(obj, "index", "uint32", prop_get_index,
557 NULL, NULL, NULL, NULL);
558 object_property_add(obj, "fdt", "struct", prop_get_fdt,
559 NULL, NULL, NULL, NULL);
560 drc->state = drck->empty_state;
561}
562
563static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
564{
565 DeviceClass *dk = DEVICE_CLASS(k);
566
567 dk->realize = realize;
568 dk->unrealize = unrealize;
569
570
571
572 dk->user_creatable = false;
573}
574
575static bool drc_physical_needed(void *opaque)
576{
577 SpaprDrcPhysical *drcp = (SpaprDrcPhysical *)opaque;
578 SpaprDrc *drc = SPAPR_DR_CONNECTOR(drcp);
579
580 if ((drc->dev && (drcp->dr_indicator == SPAPR_DR_INDICATOR_ACTIVE))
581 || (!drc->dev && (drcp->dr_indicator == SPAPR_DR_INDICATOR_INACTIVE))) {
582 return false;
583 }
584 return true;
585}
586
587static const VMStateDescription vmstate_spapr_drc_physical = {
588 .name = "spapr_drc/physical",
589 .version_id = 1,
590 .minimum_version_id = 1,
591 .needed = drc_physical_needed,
592 .fields = (VMStateField []) {
593 VMSTATE_UINT32(dr_indicator, SpaprDrcPhysical),
594 VMSTATE_END_OF_LIST()
595 }
596};
597
598static void drc_physical_reset(void *opaque)
599{
600 SpaprDrc *drc = SPAPR_DR_CONNECTOR(opaque);
601 SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(drc);
602
603 if (drc->dev) {
604 drcp->dr_indicator = SPAPR_DR_INDICATOR_ACTIVE;
605 } else {
606 drcp->dr_indicator = SPAPR_DR_INDICATOR_INACTIVE;
607 }
608}
609
610static void realize_physical(DeviceState *d, Error **errp)
611{
612 SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
613 Error *local_err = NULL;
614
615 realize(d, &local_err);
616 if (local_err) {
617 error_propagate(errp, local_err);
618 return;
619 }
620
621 vmstate_register(DEVICE(drcp), spapr_drc_index(SPAPR_DR_CONNECTOR(drcp)),
622 &vmstate_spapr_drc_physical, drcp);
623 qemu_register_reset(drc_physical_reset, drcp);
624}
625
626static void unrealize_physical(DeviceState *d, Error **errp)
627{
628 SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
629 Error *local_err = NULL;
630
631 unrealize(d, &local_err);
632 if (local_err) {
633 error_propagate(errp, local_err);
634 return;
635 }
636
637 vmstate_unregister(DEVICE(drcp), &vmstate_spapr_drc_physical, drcp);
638 qemu_unregister_reset(drc_physical_reset, drcp);
639}
640
641static void spapr_drc_physical_class_init(ObjectClass *k, void *data)
642{
643 DeviceClass *dk = DEVICE_CLASS(k);
644 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
645
646 dk->realize = realize_physical;
647 dk->unrealize = unrealize_physical;
648 drck->dr_entity_sense = physical_entity_sense;
649 drck->isolate = drc_isolate_physical;
650 drck->unisolate = drc_unisolate_physical;
651 drck->ready_state = SPAPR_DRC_STATE_PHYSICAL_CONFIGURED;
652 drck->empty_state = SPAPR_DRC_STATE_PHYSICAL_POWERON;
653}
654
655static void spapr_drc_logical_class_init(ObjectClass *k, void *data)
656{
657 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
658
659 drck->dr_entity_sense = logical_entity_sense;
660 drck->isolate = drc_isolate_logical;
661 drck->unisolate = drc_unisolate_logical;
662 drck->ready_state = SPAPR_DRC_STATE_LOGICAL_CONFIGURED;
663 drck->empty_state = SPAPR_DRC_STATE_LOGICAL_UNUSABLE;
664}
665
666static void spapr_drc_cpu_class_init(ObjectClass *k, void *data)
667{
668 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
669
670 drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU;
671 drck->typename = "CPU";
672 drck->drc_name_prefix = "CPU ";
673 drck->release = spapr_core_release;
674 drck->dt_populate = spapr_core_dt_populate;
675}
676
677static void spapr_drc_pci_class_init(ObjectClass *k, void *data)
678{
679 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
680
681 drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI;
682 drck->typename = "28";
683 drck->drc_name_prefix = "C";
684 drck->release = spapr_phb_remove_pci_device_cb;
685 drck->dt_populate = spapr_pci_dt_populate;
686}
687
688static void spapr_drc_lmb_class_init(ObjectClass *k, void *data)
689{
690 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
691
692 drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB;
693 drck->typename = "MEM";
694 drck->drc_name_prefix = "LMB ";
695 drck->release = spapr_lmb_release;
696 drck->dt_populate = spapr_lmb_dt_populate;
697}
698
699static void spapr_drc_phb_class_init(ObjectClass *k, void *data)
700{
701 SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_CLASS(k);
702
703 drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PHB;
704 drck->typename = "PHB";
705 drck->drc_name_prefix = "PHB ";
706 drck->release = spapr_phb_release;
707 drck->dt_populate = spapr_phb_dt_populate;
708}
709
710static const TypeInfo spapr_dr_connector_info = {
711 .name = TYPE_SPAPR_DR_CONNECTOR,
712 .parent = TYPE_DEVICE,
713 .instance_size = sizeof(SpaprDrc),
714 .instance_init = spapr_dr_connector_instance_init,
715 .class_size = sizeof(SpaprDrcClass),
716 .class_init = spapr_dr_connector_class_init,
717 .abstract = true,
718};
719
720static const TypeInfo spapr_drc_physical_info = {
721 .name = TYPE_SPAPR_DRC_PHYSICAL,
722 .parent = TYPE_SPAPR_DR_CONNECTOR,
723 .instance_size = sizeof(SpaprDrcPhysical),
724 .class_init = spapr_drc_physical_class_init,
725 .abstract = true,
726};
727
728static const TypeInfo spapr_drc_logical_info = {
729 .name = TYPE_SPAPR_DRC_LOGICAL,
730 .parent = TYPE_SPAPR_DR_CONNECTOR,
731 .class_init = spapr_drc_logical_class_init,
732 .abstract = true,
733};
734
735static const TypeInfo spapr_drc_cpu_info = {
736 .name = TYPE_SPAPR_DRC_CPU,
737 .parent = TYPE_SPAPR_DRC_LOGICAL,
738 .class_init = spapr_drc_cpu_class_init,
739};
740
741static const TypeInfo spapr_drc_pci_info = {
742 .name = TYPE_SPAPR_DRC_PCI,
743 .parent = TYPE_SPAPR_DRC_PHYSICAL,
744 .class_init = spapr_drc_pci_class_init,
745};
746
747static const TypeInfo spapr_drc_lmb_info = {
748 .name = TYPE_SPAPR_DRC_LMB,
749 .parent = TYPE_SPAPR_DRC_LOGICAL,
750 .class_init = spapr_drc_lmb_class_init,
751};
752
753static const TypeInfo spapr_drc_phb_info = {
754 .name = TYPE_SPAPR_DRC_PHB,
755 .parent = TYPE_SPAPR_DRC_LOGICAL,
756 .instance_size = sizeof(SpaprDrc),
757 .class_init = spapr_drc_phb_class_init,
758};
759
760
761
762SpaprDrc *spapr_drc_by_index(uint32_t index)
763{
764 Object *obj;
765 gchar *name;
766
767 name = g_strdup_printf("%s/%x", DRC_CONTAINER_PATH, index);
768 obj = object_resolve_path(name, NULL);
769 g_free(name);
770
771 return !obj ? NULL : SPAPR_DR_CONNECTOR(obj);
772}
773
774SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id)
775{
776 SpaprDrcClass *drck
777 = SPAPR_DR_CONNECTOR_CLASS(object_class_by_name(type));
778
779 return spapr_drc_by_index(drck->typeshift << DRC_INDEX_TYPE_SHIFT
780 | (id & DRC_INDEX_ID_MASK));
781}
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask)
798{
799 Object *root_container;
800 ObjectProperty *prop;
801 ObjectPropertyIterator iter;
802 uint32_t drc_count = 0;
803 GArray *drc_indexes, *drc_power_domains;
804 GString *drc_names, *drc_types;
805 int ret;
806
807
808
809
810
811
812
813 drc_indexes = g_array_new(false, true, sizeof(uint32_t));
814 drc_indexes = g_array_set_size(drc_indexes, 1);
815 drc_power_domains = g_array_new(false, true, sizeof(uint32_t));
816 drc_power_domains = g_array_set_size(drc_power_domains, 1);
817 drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
818 drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t));
819
820
821
822
823 root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
824
825 object_property_iter_init(&iter, root_container);
826 while ((prop = object_property_iter_next(&iter))) {
827 Object *obj;
828 SpaprDrc *drc;
829 SpaprDrcClass *drck;
830 uint32_t drc_index, drc_power_domain;
831
832 if (!strstart(prop->type, "link<", NULL)) {
833 continue;
834 }
835
836 obj = object_property_get_link(root_container, prop->name, NULL);
837 drc = SPAPR_DR_CONNECTOR(obj);
838 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
839
840 if (owner && (drc->owner != owner)) {
841 continue;
842 }
843
844 if ((spapr_drc_type(drc) & drc_type_mask) == 0) {
845 continue;
846 }
847
848 drc_count++;
849
850
851 drc_index = cpu_to_be32(spapr_drc_index(drc));
852 g_array_append_val(drc_indexes, drc_index);
853
854
855 drc_power_domain = cpu_to_be32(-1);
856 g_array_append_val(drc_power_domains, drc_power_domain);
857
858
859 drc_names = g_string_append(drc_names, spapr_drc_name(drc));
860 drc_names = g_string_insert_len(drc_names, -1, "\0", 1);
861
862
863 drc_types = g_string_append(drc_types, drck->typename);
864 drc_types = g_string_insert_len(drc_types, -1, "\0", 1);
865 }
866
867
868
869
870 *(uint32_t *)drc_indexes->data = cpu_to_be32(drc_count);
871 *(uint32_t *)drc_power_domains->data = cpu_to_be32(drc_count);
872 *(uint32_t *)drc_names->str = cpu_to_be32(drc_count);
873 *(uint32_t *)drc_types->str = cpu_to_be32(drc_count);
874
875 ret = fdt_setprop(fdt, offset, "ibm,drc-indexes",
876 drc_indexes->data,
877 drc_indexes->len * sizeof(uint32_t));
878 if (ret) {
879 error_report("Couldn't create ibm,drc-indexes property");
880 goto out;
881 }
882
883 ret = fdt_setprop(fdt, offset, "ibm,drc-power-domains",
884 drc_power_domains->data,
885 drc_power_domains->len * sizeof(uint32_t));
886 if (ret) {
887 error_report("Couldn't finalize ibm,drc-power-domains property");
888 goto out;
889 }
890
891 ret = fdt_setprop(fdt, offset, "ibm,drc-names",
892 drc_names->str, drc_names->len);
893 if (ret) {
894 error_report("Couldn't finalize ibm,drc-names property");
895 goto out;
896 }
897
898 ret = fdt_setprop(fdt, offset, "ibm,drc-types",
899 drc_types->str, drc_types->len);
900 if (ret) {
901 error_report("Couldn't finalize ibm,drc-types property");
902 goto out;
903 }
904
905out:
906 g_array_free(drc_indexes, true);
907 g_array_free(drc_power_domains, true);
908 g_string_free(drc_names, true);
909 g_string_free(drc_types, true);
910
911 return ret;
912}
913
914
915
916
917
918static uint32_t rtas_set_isolation_state(uint32_t idx, uint32_t state)
919{
920 SpaprDrc *drc = spapr_drc_by_index(idx);
921 SpaprDrcClass *drck;
922
923 if (!drc) {
924 return RTAS_OUT_NO_SUCH_INDICATOR;
925 }
926
927 trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state);
928
929 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
930
931 switch (state) {
932 case SPAPR_DR_ISOLATION_STATE_ISOLATED:
933 return drck->isolate(drc);
934
935 case SPAPR_DR_ISOLATION_STATE_UNISOLATED:
936 return drck->unisolate(drc);
937
938 default:
939 return RTAS_OUT_PARAM_ERROR;
940 }
941}
942
943static uint32_t rtas_set_allocation_state(uint32_t idx, uint32_t state)
944{
945 SpaprDrc *drc = spapr_drc_by_index(idx);
946
947 if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_LOGICAL)) {
948 return RTAS_OUT_NO_SUCH_INDICATOR;
949 }
950
951 trace_spapr_drc_set_allocation_state(spapr_drc_index(drc), state);
952
953 switch (state) {
954 case SPAPR_DR_ALLOCATION_STATE_USABLE:
955 return drc_set_usable(drc);
956
957 case SPAPR_DR_ALLOCATION_STATE_UNUSABLE:
958 return drc_set_unusable(drc);
959
960 default:
961 return RTAS_OUT_PARAM_ERROR;
962 }
963}
964
965static uint32_t rtas_set_dr_indicator(uint32_t idx, uint32_t state)
966{
967 SpaprDrc *drc = spapr_drc_by_index(idx);
968
969 if (!drc || !object_dynamic_cast(OBJECT(drc), TYPE_SPAPR_DRC_PHYSICAL)) {
970 return RTAS_OUT_NO_SUCH_INDICATOR;
971 }
972 if ((state != SPAPR_DR_INDICATOR_INACTIVE)
973 && (state != SPAPR_DR_INDICATOR_ACTIVE)
974 && (state != SPAPR_DR_INDICATOR_IDENTIFY)
975 && (state != SPAPR_DR_INDICATOR_ACTION)) {
976 return RTAS_OUT_PARAM_ERROR;
977 }
978
979 trace_spapr_drc_set_dr_indicator(idx, state);
980 SPAPR_DRC_PHYSICAL(drc)->dr_indicator = state;
981 return RTAS_OUT_SUCCESS;
982}
983
984static void rtas_set_indicator(PowerPCCPU *cpu, SpaprMachineState *spapr,
985 uint32_t token,
986 uint32_t nargs, target_ulong args,
987 uint32_t nret, target_ulong rets)
988{
989 uint32_t type, idx, state;
990 uint32_t ret = RTAS_OUT_SUCCESS;
991
992 if (nargs != 3 || nret != 1) {
993 ret = RTAS_OUT_PARAM_ERROR;
994 goto out;
995 }
996
997 type = rtas_ld(args, 0);
998 idx = rtas_ld(args, 1);
999 state = rtas_ld(args, 2);
1000
1001 switch (type) {
1002 case RTAS_SENSOR_TYPE_ISOLATION_STATE:
1003 ret = rtas_set_isolation_state(idx, state);
1004 break;
1005 case RTAS_SENSOR_TYPE_DR:
1006 ret = rtas_set_dr_indicator(idx, state);
1007 break;
1008 case RTAS_SENSOR_TYPE_ALLOCATION_STATE:
1009 ret = rtas_set_allocation_state(idx, state);
1010 break;
1011 default:
1012 ret = RTAS_OUT_NOT_SUPPORTED;
1013 }
1014
1015out:
1016 rtas_st(rets, 0, ret);
1017}
1018
1019static void rtas_get_sensor_state(PowerPCCPU *cpu, SpaprMachineState *spapr,
1020 uint32_t token, uint32_t nargs,
1021 target_ulong args, uint32_t nret,
1022 target_ulong rets)
1023{
1024 uint32_t sensor_type;
1025 uint32_t sensor_index;
1026 uint32_t sensor_state = 0;
1027 SpaprDrc *drc;
1028 SpaprDrcClass *drck;
1029 uint32_t ret = RTAS_OUT_SUCCESS;
1030
1031 if (nargs != 2 || nret != 2) {
1032 ret = RTAS_OUT_PARAM_ERROR;
1033 goto out;
1034 }
1035
1036 sensor_type = rtas_ld(args, 0);
1037 sensor_index = rtas_ld(args, 1);
1038
1039 if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) {
1040
1041 trace_spapr_rtas_get_sensor_state_not_supported(sensor_index,
1042 sensor_type);
1043 ret = RTAS_OUT_NOT_SUPPORTED;
1044 goto out;
1045 }
1046
1047 drc = spapr_drc_by_index(sensor_index);
1048 if (!drc) {
1049 trace_spapr_rtas_get_sensor_state_invalid(sensor_index);
1050 ret = RTAS_OUT_PARAM_ERROR;
1051 goto out;
1052 }
1053 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
1054 sensor_state = drck->dr_entity_sense(drc);
1055
1056out:
1057 rtas_st(rets, 0, ret);
1058 rtas_st(rets, 1, sensor_state);
1059}
1060
1061
1062
1063
1064
1065
1066#define CC_IDX_NODE_NAME_OFFSET 2
1067#define CC_IDX_PROP_NAME_OFFSET 2
1068#define CC_IDX_PROP_LEN 3
1069#define CC_IDX_PROP_DATA_OFFSET 4
1070#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
1071#define CC_WA_LEN 4096
1072
1073static void configure_connector_st(target_ulong addr, target_ulong offset,
1074 const void *buf, size_t len)
1075{
1076 cpu_physical_memory_write(ppc64_phys_to_real(addr + offset),
1077 buf, MIN(len, CC_WA_LEN - offset));
1078}
1079
1080static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
1081 SpaprMachineState *spapr,
1082 uint32_t token, uint32_t nargs,
1083 target_ulong args, uint32_t nret,
1084 target_ulong rets)
1085{
1086 uint64_t wa_addr;
1087 uint64_t wa_offset;
1088 uint32_t drc_index;
1089 SpaprDrc *drc;
1090 SpaprDrcClass *drck;
1091 SpaprDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE;
1092 int rc;
1093
1094 if (nargs != 2 || nret != 1) {
1095 rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
1096 return;
1097 }
1098
1099 wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0);
1100
1101 drc_index = rtas_ld(wa_addr, 0);
1102 drc = spapr_drc_by_index(drc_index);
1103 if (!drc) {
1104 trace_spapr_rtas_ibm_configure_connector_invalid(drc_index);
1105 rc = RTAS_OUT_PARAM_ERROR;
1106 goto out;
1107 }
1108
1109 if ((drc->state != SPAPR_DRC_STATE_LOGICAL_UNISOLATE)
1110 && (drc->state != SPAPR_DRC_STATE_PHYSICAL_UNISOLATE)
1111 && (drc->state != SPAPR_DRC_STATE_LOGICAL_CONFIGURED)
1112 && (drc->state != SPAPR_DRC_STATE_PHYSICAL_CONFIGURED)) {
1113
1114
1115
1116
1117
1118 rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
1119 goto out;
1120 }
1121
1122 drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
1123
1124 if (!drc->fdt) {
1125 Error *local_err = NULL;
1126 void *fdt;
1127 int fdt_size;
1128
1129 fdt = create_device_tree(&fdt_size);
1130
1131 if (drck->dt_populate(drc, spapr, fdt, &drc->fdt_start_offset,
1132 &local_err)) {
1133 g_free(fdt);
1134 error_free(local_err);
1135 rc = SPAPR_DR_CC_RESPONSE_ERROR;
1136 goto out;
1137 }
1138
1139 drc->fdt = fdt;
1140 drc->ccs_offset = drc->fdt_start_offset;
1141 drc->ccs_depth = 0;
1142 }
1143
1144 do {
1145 uint32_t tag;
1146 const char *name;
1147 const struct fdt_property *prop;
1148 int fdt_offset_next, prop_len;
1149
1150 tag = fdt_next_tag(drc->fdt, drc->ccs_offset, &fdt_offset_next);
1151
1152 switch (tag) {
1153 case FDT_BEGIN_NODE:
1154 drc->ccs_depth++;
1155 name = fdt_get_name(drc->fdt, drc->ccs_offset, NULL);
1156
1157
1158 wa_offset = CC_VAL_DATA_OFFSET;
1159 rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
1160 configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
1161 resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
1162 break;
1163 case FDT_END_NODE:
1164 drc->ccs_depth--;
1165 if (drc->ccs_depth == 0) {
1166 uint32_t drc_index = spapr_drc_index(drc);
1167
1168
1169 trace_spapr_drc_set_configured(drc_index);
1170 drc->state = drck->ready_state;
1171
1172
1173
1174
1175 drc->ccs_offset = drc->fdt_start_offset;
1176 drc->ccs_depth = 0;
1177 fdt_offset_next = drc->fdt_start_offset;
1178 resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
1179 } else {
1180 resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
1181 }
1182 break;
1183 case FDT_PROP:
1184 prop = fdt_get_property_by_offset(drc->fdt, drc->ccs_offset,
1185 &prop_len);
1186 name = fdt_string(drc->fdt, fdt32_to_cpu(prop->nameoff));
1187
1188
1189 wa_offset = CC_VAL_DATA_OFFSET;
1190 rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
1191 configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
1192
1193
1194
1195
1196
1197 wa_offset += strlen(name) + 1,
1198 rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
1199 rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
1200 configure_connector_st(wa_addr, wa_offset, prop->data, prop_len);
1201 resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
1202 break;
1203 case FDT_END:
1204 resp = SPAPR_DR_CC_RESPONSE_ERROR;
1205 default:
1206
1207 break;
1208 }
1209 if (drc->ccs_offset >= 0) {
1210 drc->ccs_offset = fdt_offset_next;
1211 }
1212 } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE);
1213
1214 rc = resp;
1215out:
1216 rtas_st(rets, 0, rc);
1217}
1218
1219static void spapr_drc_register_types(void)
1220{
1221 type_register_static(&spapr_dr_connector_info);
1222 type_register_static(&spapr_drc_physical_info);
1223 type_register_static(&spapr_drc_logical_info);
1224 type_register_static(&spapr_drc_cpu_info);
1225 type_register_static(&spapr_drc_pci_info);
1226 type_register_static(&spapr_drc_lmb_info);
1227 type_register_static(&spapr_drc_phb_info);
1228
1229 spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator",
1230 rtas_set_indicator);
1231 spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state",
1232 rtas_get_sensor_state);
1233 spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector",
1234 rtas_ibm_configure_connector);
1235}
1236type_init(spapr_drc_register_types)
1237