From: Ruslan Ruslichenko <Ruslan_Ruslichenko@epam.com>
The patch adds infrastructure to parse device tree
and associate fdt nodes and created objects.
This will be used during instantiating machine from the
devices tree.
Signed-off-by: Ruslan Ruslichenko <Ruslan_Ruslichenko@epam.com>
---
hw/core/fdt_generic.c | 71 +++++++++++++++++++++++++++++++++++
include/hw/core/fdt_generic.h | 42 ++++++++++++++++++++-
2 files changed, 112 insertions(+), 1 deletion(-)
diff --git a/hw/core/fdt_generic.c b/hw/core/fdt_generic.c
index 65e3c1efa3..da60de7a26 100644
--- a/hw/core/fdt_generic.c
+++ b/hw/core/fdt_generic.c
@@ -29,7 +29,10 @@
#include "qemu/osdep.h"
#include "hw/core/fdt_generic.h"
#include "hw/core/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "qemu/coroutine.h"
#include "qemu/log.h"
+#include "system/reset.h"
#define FDT_GENERIC_MAX_PATTERN_LEN 1024
@@ -108,3 +111,71 @@ int fdt_init_inst_bind(char *node_path, FDTMachineInfo *fdti,
{
return fdt_init_search_table(node_path, fdti, name, &inst_bind_list_head);
}
+
+void fdt_init_yield(FDTMachineInfo *fdti)
+{
+ static int yield_index;
+ int this_yield = yield_index++;
+
+ qemu_log_mask(LOG_FDT, "Yield #%d\n", this_yield);
+ qemu_co_queue_wait(fdti->cq, NULL);
+ qemu_log_mask(LOG_FDT, "Unyield #%d\n", this_yield);
+}
+
+void fdt_init_set_opaque(FDTMachineInfo *fdti, const char *node_path,
+ void *opaque)
+{
+ FDTDevOpaque *dp;
+ for (dp = fdti->dev_opaques;
+ dp->node_path && strcmp(dp->node_path, node_path);
+ dp++)
+ ;
+ if (!dp->node_path) {
+ dp->node_path = strdup(node_path);
+ }
+ dp->opaque = opaque;
+}
+
+int fdt_init_has_opaque(FDTMachineInfo *fdti, const char *node_path)
+{
+ FDTDevOpaque *dp;
+ for (dp = fdti->dev_opaques; dp->node_path; dp++) {
+ if (!strcmp(dp->node_path, node_path)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void *fdt_init_get_opaque(FDTMachineInfo *fdti, const char *node_path)
+{
+ FDTDevOpaque *dp;
+ for (dp = fdti->dev_opaques; dp->node_path; dp++) {
+ if (!strcmp(dp->node_path, node_path)) {
+ return dp->opaque;
+ }
+ }
+ return NULL;
+}
+
+FDTMachineInfo *fdt_init_new_fdti(void *fdt)
+{
+ FDTMachineInfo *fdti = g_malloc0(sizeof(*fdti));
+ fdti->fdt = fdt;
+ fdti->cq = g_malloc0(sizeof(*(fdti->cq)));
+ qemu_co_queue_init(fdti->cq);
+ fdti->dev_opaques = g_malloc0(sizeof(*(fdti->dev_opaques)) *
+ (devtree_get_num_nodes(fdt) + 1));
+ return fdti;
+}
+
+void fdt_init_destroy_fdti(FDTMachineInfo *fdti)
+{
+ FDTDevOpaque *dp;
+
+ for (dp = fdti->dev_opaques; dp->node_path; dp++) {
+ g_free(dp->node_path);
+ }
+ g_free(fdti->dev_opaques);
+ g_free(fdti);
+}
diff --git a/include/hw/core/fdt_generic.h b/include/hw/core/fdt_generic.h
index 3d8ec2f7ff..d204ceda43 100644
--- a/include/hw/core/fdt_generic.h
+++ b/include/hw/core/fdt_generic.h
@@ -9,9 +9,33 @@
#define FDT_GENERIC_H
#include "qemu/help-texts.h"
+#include "hw/core/irq.h"
#include "system/device_tree.h"
+#include "qemu/coroutine.h"
+
+typedef struct FDTDevOpaque {
+ char *node_path;
+ void *opaque;
+} FDTDevOpaque;
+
+typedef struct FDTMachineInfo {
+ /* the fdt blob */
+ void *fdt;
+ /* irq descriptors for top level int controller */
+ qemu_irq *irq_base;
+ /* per-device specific opaques */
+ FDTDevOpaque *dev_opaques;
+ /* recheck coroutine queue */
+ CoQueue *cq;
+} FDTMachineInfo;
-typedef struct FDTMachineInfo FDTMachineInfo;
+/*
+ * create a new FDTMachineInfo. The client is responsible for setting irq_base.
+ * Client must call fdt_init_destroy_fdti to cleanup
+ */
+
+FDTMachineInfo *fdt_init_new_fdti(void *fdt);
+void fdt_init_destroy_fdti(FDTMachineInfo *fdti);
typedef int (*FDTInitFn)(char *, FDTMachineInfo *, void *);
@@ -32,6 +56,22 @@ int fdt_init_compat(char *, FDTMachineInfo *, const char *);
void add_to_inst_bind_table(FDTInitFn, const char *, void *);
int fdt_init_inst_bind(char *, FDTMachineInfo *, const char *);
+/*
+ * Called from FDTInitFn's to inform the framework that a dependency is
+ * unresolved and the calling context needs to wait for another device to
+ * instantiate first. The calling thread will suspend until a change in state
+ * in the argument fdt machine is detected.
+ */
+
+void fdt_init_yield(FDTMachineInfo *);
+
+/* set, check and get per device opaques. Keyed by fdt node_paths */
+
+void fdt_init_set_opaque(FDTMachineInfo *fdti, const char *node_path,
+ void *opaque);
+int fdt_init_has_opaque(FDTMachineInfo *fdti, const char *node_path);
+void *fdt_init_get_opaque(FDTMachineInfo *fdti, const char *node_path);
+
/* statically register a FDTInitFn as being associate with a compatibility */
#define fdt_register_compatibility_opaque(function, compat, n, opaque) \
--
2.43.0