* [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees
@ 2016-04-20 2:33 David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code David Gibson
` (10 more replies)
0 siblings, 11 replies; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
This RFC series suggests a new approach to constructing IEE1275 or
"fdt" style device trees for use by guests. At the moment we
generally do that with libfdt which works, but as the amount of device
tree manipulation we need in qemu grows, it becomes an increasingly
poor choice.
This introduces a new "qdt" mini-library for manipulating device trees
in an internal format, then flattening them to fdt. It makes a start
on converting the pseries machine type (probably the heaviest user of
device trees) to this approach.
David Gibson (11):
qdt: IEEE1275-style device tree utility code
pseries: Split device tree construction from device tree load
pseries: Remove rtas_addr and fdt_addr fields from machinestate
pseries: Make spapr_create_fdt_skel() get information from machine
state
pseries: Build device tree only at reset time
pseries: Consolidate RTAS loading
pseries: Move adding of fdt reserve map entries
pseries: Start using qdt library for building device tree
pseries: Consolidate construction of /chosen device tree node
pseries: Consolidate construction of /rtas device tree node
pseries: Remove unused callbacks from sPAPR VIO bus state
hw/ppc/spapr.c | 567 ++++++++++++++++++++++-----------------------
hw/ppc/spapr_events.c | 19 --
hw/ppc/spapr_rtas.c | 82 +++----
hw/ppc/spapr_vio.c | 16 +-
include/hw/ppc/spapr.h | 12 +-
include/hw/ppc/spapr_vio.h | 4 +-
include/qemu/qdt.h | 102 ++++++++
util/Makefile.objs | 1 +
util/qdt.c | 262 +++++++++++++++++++++
9 files changed, 679 insertions(+), 386 deletions(-)
create mode 100644 include/qemu/qdt.h
create mode 100644 util/qdt.c
--
2.5.5
^ permalink raw reply [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 6:01 ` Alexey Kardashevskiy
2016-04-26 11:00 ` Thomas Huth
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 02/11] pseries: Split device tree construction from device tree load David Gibson
` (9 subsequent siblings)
10 siblings, 2 replies; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
A number of guests supported by qemu use IEEE12750 (Open Firmware)
style device trees for hardware discovery. In some cases (mac99,
pseries) they get this device tree via calls to an in-guest Open
Firmware implementation, in others (many ppc and arm embedded
machines) they consume the flattened ("fdt" or "dtb") format described
in ePAPR amongst other places. In some cases this device tree is
constructed in guest firmware, in others by qemu and in some cases
it's a hybrid.
The upshot is that a number of qemu machine types need to construct
and/or manipulate device trees. Particularly with the pseries machine
type, the complexity of manipulation it needs has been gradually
increasing over time.
For now, these machine types have generally worked with the device
tree in the flattened format, using either libfdt directly or the
wrappers in device_tree.c. However, the fdt format was designed
primarily for transferring device trees between components, not for
runtime manipulation:
* fdt provides no persistent handles on nodes
Nodes are referenced using offsets in the stream which can be
altered by insertions or deletions elsewhere in the tree
* libfdt operations can fail
At any time the fdt lives in a limited size buffer, and
operations can fail if it fills. This can be handled by
resizing the buffer, but that means logic to catch this case
on essentially every fdt operation, which is fiddly (in
practice we usually just allocate a buffer with plenty of
space and treat failures as fatal errors).
* fdt manipulation is slow
This probably isn't a problem in practice, but because it
uses memmove() liberally, even trivial operations on an fdt
are usually O(n) in the size of the whole tree. This can
often make the obvious way of constructing the tree O(n^2) or
worse. This could cause noticeable slow downs if someone
builds a guest with hundreds or thousands of devices, which
is an unusual but not unreasonable use case.
This patch introduces a new utility library "qdt" for runtime
manipulation of device trees. The intention is that machine type code
can use these routines to construct the device tree conveniently,
using a pointer-based representation doesn't have the limitations
above. They can then use qdt_flatten() to convert the completed tree
to fdt format as a single O(n) operation to pass to the guest.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
include/qemu/qdt.h | 102 +++++++++++++++++++++
util/Makefile.objs | 1 +
util/qdt.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 365 insertions(+)
create mode 100644 include/qemu/qdt.h
create mode 100644 util/qdt.c
diff --git a/include/qemu/qdt.h b/include/qemu/qdt.h
new file mode 100644
index 0000000..bff7143
--- /dev/null
+++ b/include/qemu/qdt.h
@@ -0,0 +1,102 @@
+/*
+ * Functions for manipulating IEEE1275 (Open Firmware) style device
+ * trees.
+ *
+ * Copyright David Gibson, Red Hat Inc. 2016
+ *
+ * This work is licensed unter the GNU GPL version 2 or (at your
+ * option) any later version.
+ */
+#ifndef QEMU_QDT_H__
+#define QEMU_QDT_H__
+
+#include <string.h>
+#include <stdint.h>
+#include <glib.h>
+#include "qemu/queue.h"
+
+typedef struct QDTProperty QDTProperty;
+typedef struct QDTNode QDTNode;
+
+struct QDTProperty {
+ gchar *name;
+ QTAILQ_ENTRY(QDTProperty) list;
+ gsize len;
+ uint8_t val[];
+};
+
+struct QDTNode {
+ gchar *name;
+ QDTNode *parent;
+ QTAILQ_HEAD(, QDTProperty) properties;
+ QTAILQ_HEAD(, QDTNode) children;
+ QTAILQ_ENTRY(QDTNode) sibling;
+};
+
+/*
+ * Node functions
+ */
+
+QDTNode *qdt_new_node(const gchar *name);
+QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path);
+QDTNode *qdt_get_node(QDTNode *root, const gchar *path);
+QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name);
+
+static inline QDTNode *qdt_new_tree(void)
+{
+ return qdt_new_node("");
+}
+
+/*
+ * Property functions
+ */
+
+QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len);
+const QDTProperty *qdt_getprop(const QDTNode *node, const gchar *name);
+void qdt_delprop(QDTNode *node, const gchar *name);
+const QDTProperty *qdt_setprop(QDTNode *node, const gchar *name,
+ gconstpointer val, gsize len);
+const QDTProperty *qdt_setprop_cells_(QDTNode *node, const gchar *name,
+ const uint32_t *val, gsize len);
+const QDTProperty *qdt_setprop_u64s_(QDTNode *node, const char *name,
+ const uint64_t *val, gsize len);
+const QDTProperty *qdt_setprop_string(QDTNode *node, const gchar *name,
+ const gchar *val);
+void qdt_set_phandle(QDTNode *node, uint32_t phandle);
+
+#define qdt_setprop_bytes(node, name, ...) \
+ ({ \
+ uint8_t vals[] = { __VA_ARGS__ }; \
+ qdt_setprop((node), (name), vals, sizeof(vals)); \
+ })
+#define qdt_setprop_cells(node, name, ...) \
+ ({ \
+ uint32_t vals[] = { __VA_ARGS__ }; \
+ qdt_setprop_cells_((node), (name), \
+ vals, sizeof(vals) / sizeof(vals[0])); \
+ })
+#define qdt_setprop_u64s(node, name, ...) \
+ ({ \
+ uint64_t vals[] = { __VA_ARGS__ }; \
+ qdt_setprop_u64s_((node), (name), \
+ vals, sizeof(vals) / sizeof(vals[0])); \
+ })
+static inline const QDTProperty *qdt_setprop_empty(QDTNode *node,
+ const gchar *name)
+{
+ return qdt_setprop_bytes(node, name);
+}
+static inline const QDTProperty *qdt_setprop_dup(QDTNode *node,
+ const gchar *name,
+ const QDTProperty *oldprop)
+{
+ return qdt_setprop(node, name, oldprop->val, oldprop->len);
+}
+
+/*
+ * Whole tree functions
+ */
+
+void *qdt_flatten(QDTNode *root, gsize bufsize, Error **errp);
+
+#endif /* QEMU_QDT_H__ */
diff --git a/util/Makefile.objs b/util/Makefile.objs
index a8a777e..f1d639f 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -32,3 +32,4 @@ util-obj-y += buffer.o
util-obj-y += timed-average.o
util-obj-y += base64.o
util-obj-y += log.o
+util-obj-y += qdt.o
diff --git a/util/qdt.c b/util/qdt.c
new file mode 100644
index 0000000..e3a449a
--- /dev/null
+++ b/util/qdt.c
@@ -0,0 +1,262 @@
+/*
+ * Functions for manipulating IEEE1275 (Open Firmware) style device
+ * trees.
+ *
+ * Copyright David Gibson, Red Hat Inc. 2016
+ *
+ * This work is licensed unter the GNU GPL version 2 or (at your
+ * option) any later version.
+ */
+
+#include <libfdt.h>
+#include <stdbool.h>
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/qdt.h"
+#include "qemu/error-report.h"
+
+/*
+ * Node functions
+ */
+
+QDTNode *qdt_new_node(const gchar *name)
+{
+ QDTNode *node = g_new0(QDTNode, 1);
+
+ g_assert(!strchr(name, '/'));
+
+ node->name = g_strdup(name);
+ QTAILQ_INIT(&node->properties);
+ QTAILQ_INIT(&node->children);
+
+ return node;
+}
+
+static QDTNode *get_subnode(QDTNode *parent, const gchar *name, size_t namelen)
+{
+ QDTNode *child;
+
+ g_assert(!memchr(name, '/', namelen));
+
+ QTAILQ_FOREACH(child, &parent->children, sibling) {
+ if ((strlen(child->name) == namelen)
+ && (memcmp(child->name, name, namelen) == 0)) {
+ return child;
+ }
+ }
+
+ return NULL;
+}
+
+QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path)
+{
+ const gchar *slash;
+ gsize seglen;
+
+ do {
+ slash = strchr(path, '/');
+ seglen = slash ? slash - path : strlen(path);
+
+ node = get_subnode(node, path, seglen);
+ path += seglen + 1;
+ } while (node && slash);
+
+ return node;
+}
+
+QDTNode *qdt_get_node(QDTNode *root, const gchar *path)
+{
+ g_assert(!root->parent);
+ g_assert(path[0] == '/');
+ return qdt_get_node_relative(root, path + 1);
+}
+
+QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name)
+{
+ QDTNode *new = qdt_new_node(name);
+
+ new->parent = parent;
+ QTAILQ_INSERT_TAIL(&parent->children, new, sibling);
+ return new;
+}
+
+/*
+ * Property functions
+ */
+
+QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
+{
+ QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
+
+ prop->name = g_strdup(name);
+ prop->len = len;
+ memcpy(prop->val, val, len);
+ return prop;
+}
+
+static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
+{
+ QDTProperty *prop;
+
+ QTAILQ_FOREACH(prop, &node->properties, list) {
+ if (strcmp(prop->name, name) == 0) {
+ return prop;
+ }
+ }
+ return NULL;
+}
+
+const QDTProperty *qdt_getprop(const QDTNode *node, const gchar *name)
+{
+ return getprop_(node, name);
+}
+
+void qdt_delprop(QDTNode *node, const gchar *name)
+{
+ QDTProperty *prop = getprop_(node, name);
+
+ if (prop) {
+ QTAILQ_REMOVE(&node->properties, prop, list);
+ g_free(prop->name);
+ g_free(prop);
+ }
+}
+
+const QDTProperty *qdt_setprop(QDTNode *node, const gchar *name,
+ gconstpointer val, gsize len)
+{
+ QDTProperty *prop;
+
+ qdt_delprop(node, name);
+
+ prop = g_malloc0(sizeof(*prop) + len);
+ prop->name = g_strdup(name);
+ prop->len = len;
+ memcpy(prop->val, val, len);
+ QTAILQ_INSERT_TAIL(&node->properties, prop, list);
+ return prop;
+}
+
+const QDTProperty *qdt_setprop_string(QDTNode *node, const gchar *name,
+ const gchar *val)
+{
+ return qdt_setprop(node, name, val, strlen(val) + 1);
+}
+
+const QDTProperty *qdt_setprop_cells_(QDTNode *node, const gchar *name,
+ const uint32_t *val, gsize len)
+{
+ uint32_t swapval[len];
+ gsize i;
+
+ for (i = 0; i < len; i++) {
+ swapval[i] = cpu_to_fdt32(val[i]);
+ }
+ return qdt_setprop(node, name, swapval, sizeof(swapval));
+}
+
+const QDTProperty *qdt_setprop_u64s_(QDTNode *node, const char *name,
+ const uint64_t *val, gsize len)
+{
+ uint64_t swapval[len];
+ gsize i;
+
+ for (i = 0; i < len; i++) {
+ swapval[i] = cpu_to_fdt64(val[i]);
+ }
+ return qdt_setprop(node, name, swapval, sizeof(swapval));
+}
+
+void qdt_set_phandle(QDTNode *node, uint32_t phandle)
+{
+ g_assert((phandle != 0) && (phandle != (uint32_t)-1));
+ qdt_setprop_cells(node, "linux,phandle", phandle);
+ qdt_setprop_cells(node, "phandle", phandle);
+}
+
+/*
+ * Whole tree functions
+ */
+
+static void qdt_flatten_node(void *fdt, QDTNode *node, Error **errp)
+{
+ QDTProperty *prop;
+ QDTNode *subnode;
+ Error *local_err = NULL;
+ int ret;
+
+ ret = fdt_begin_node(fdt, node->name);
+ if (ret < 0) {
+ error_setg(errp, "Error flattening device tree: fdt_begin_node(): %s",
+ fdt_strerror(ret));
+ return;
+ }
+
+ QTAILQ_FOREACH(prop, &node->properties, list) {
+ ret = fdt_property(fdt, prop->name, prop->val, prop->len);
+ if (ret < 0) {
+ error_setg(errp, "Error flattening device tree: fdt_property(): %s",
+ fdt_strerror(ret));
+ return;
+ }
+ }
+
+ QTAILQ_FOREACH(subnode, &node->children, sibling) {
+ qdt_flatten_node(fdt, subnode, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
+ ret = fdt_end_node(fdt);
+ if (ret < 0) {
+ error_setg(errp, "Error flattening device tree: fdt_end_node(): %s",
+ fdt_strerror(ret));
+ return;
+ }
+}
+
+void *qdt_flatten(QDTNode *root, gsize bufsize, Error **errp)
+{
+ void *fdt = g_malloc0(bufsize);
+ Error *local_err = NULL;
+ int ret;
+
+ assert(!root->parent); /* Should be a root node */
+
+ ret = fdt_create(fdt, bufsize);
+ if (ret < 0) {
+ error_setg(errp, "Error flattening device tree: fdt_create(): %s",
+ fdt_strerror(ret));
+ goto fail;
+ }
+
+ ret = fdt_finish_reservemap(fdt);
+ if (ret < 0) {
+ error_setg(errp,
+ "Error flattening device tree: fdt_finish_reservemap(): %s",
+ fdt_strerror(ret));
+ goto fail;
+ }
+
+ qdt_flatten_node(fdt, root, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ goto fail;
+ }
+
+ ret = fdt_finish(fdt);
+ if (ret < 0) {
+ error_setg(errp, "Error flattening device tree: fdt_finish(): %s",
+ fdt_strerror(ret));
+ goto fail;
+ }
+
+ return fdt;
+
+fail:
+ g_free(fdt);
+ return NULL;
+}
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 02/11] pseries: Split device tree construction from device tree load
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-20 18:15 ` Thomas Huth
2016-04-21 5:31 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 03/11] pseries: Remove rtas_addr and fdt_addr fields from machinestate David Gibson
` (8 subsequent siblings)
10 siblings, 2 replies; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
spapr_finalize_fdt() both finishes building the device tree for the guest
and loads it into guest memory. For future cleanups, it's going to be
more convenient to do these two things separately, so split them apart.
The loading portion is pretty trivial, so we move it inline into the
caller, ppc_spapr_reset().
We also rename spapr_finalize_fdt(), because the current name is going to
become inaccurate.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 41 ++++++++++++++++++++++-------------------
1 file changed, 22 insertions(+), 19 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index feaab08..26b95ce 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -899,10 +899,9 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
return 0;
}
-static void spapr_finalize_fdt(sPAPRMachineState *spapr,
- hwaddr fdt_addr,
- hwaddr rtas_addr,
- hwaddr rtas_size)
+static void *spapr_build_fdt(sPAPRMachineState *spapr,
+ hwaddr rtas_addr,
+ hwaddr rtas_size)
{
MachineState *machine = MACHINE(qdev_get_machine());
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
@@ -988,19 +987,8 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr,
_FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
}
- _FDT((fdt_pack(fdt)));
-
- if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
- error_report("FDT too big ! 0x%x bytes (max is 0x%x)",
- fdt_totalsize(fdt), FDT_MAX_SIZE);
- exit(1);
- }
-
- qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
- cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
-
g_free(bootlist);
- g_free(fdt);
+ return fdt;
}
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
@@ -1138,6 +1126,8 @@ static void ppc_spapr_reset(void)
sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
PowerPCCPU *first_ppc_cpu;
uint32_t rtas_limit;
+ void *fdt;
+ int rc;
/* Check for unknown sysbus devices */
foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);
@@ -1164,14 +1154,27 @@ static void ppc_spapr_reset(void)
spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
- /* Load the fdt */
- spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
- spapr->rtas_size);
+ fdt = spapr_build_fdt(spapr, spapr->rtas_addr, spapr->rtas_size);
/* Copy RTAS over */
cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob,
spapr->rtas_size);
+ rc = fdt_pack(fdt);
+
+ /* Should only fail if we've built a corrupted tree */
+ assert(rc == 0);
+
+ if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
+ error_report("FDT too big ! 0x%x bytes (max is 0x%x)",
+ fdt_totalsize(fdt), FDT_MAX_SIZE);
+ exit(1);
+ }
+
+ /* Load the fdt */
+ qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
+ cpu_physical_memory_write(spapr->fdt_addr, fdt, fdt_totalsize(fdt));
+
/* Set up the entry state */
first_ppc_cpu = POWERPC_CPU(first_cpu);
first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 03/11] pseries: Remove rtas_addr and fdt_addr fields from machinestate
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 02/11] pseries: Split device tree construction from device tree load David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-20 18:19 ` Thomas Huth
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 04/11] pseries: Make spapr_create_fdt_skel() get information from machine state David Gibson
` (7 subsequent siblings)
10 siblings, 2 replies; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
These values are used only within ppc_spapr_reset(), so just change them
to local variables.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 14 +++++++-------
include/hw/ppc/spapr.h | 1 -
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 26b95ce..b123078 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1126,6 +1126,7 @@ static void ppc_spapr_reset(void)
sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
PowerPCCPU *first_ppc_cpu;
uint32_t rtas_limit;
+ hwaddr rtas_addr, fdt_addr;
void *fdt;
int rc;
@@ -1151,14 +1152,13 @@ static void ppc_spapr_reset(void)
* processed with 32-bit real mode code if necessary
*/
rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR);
- spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
- spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
+ rtas_addr = rtas_limit - RTAS_MAX_SIZE;
+ fdt_addr = rtas_addr - FDT_MAX_SIZE;
- fdt = spapr_build_fdt(spapr, spapr->rtas_addr, spapr->rtas_size);
+ fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
/* Copy RTAS over */
- cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob,
- spapr->rtas_size);
+ cpu_physical_memory_write(rtas_addr, spapr->rtas_blob, spapr->rtas_size);
rc = fdt_pack(fdt);
@@ -1173,11 +1173,11 @@ static void ppc_spapr_reset(void)
/* Load the fdt */
qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
- cpu_physical_memory_write(spapr->fdt_addr, fdt, fdt_totalsize(fdt));
+ cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
/* Set up the entry state */
first_ppc_cpu = POWERPC_CPU(first_cpu);
- first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
+ first_ppc_cpu->env.gpr[3] = fdt_addr;
first_ppc_cpu->env.gpr[5] = 0;
first_cpu->halted = 0;
first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT;
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 815d5ee..655ffe9 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -56,7 +56,6 @@ struct sPAPRMachineState {
uint32_t htab_shift;
hwaddr rma_size;
int vrma_adjust;
- hwaddr fdt_addr, rtas_addr;
ssize_t rtas_size;
void *rtas_blob;
void *fdt_skel;
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 04/11] pseries: Make spapr_create_fdt_skel() get information from machine state
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
` (2 preceding siblings ...)
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 03/11] pseries: Remove rtas_addr and fdt_addr fields from machinestate David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-26 17:41 ` Thomas Huth
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time David Gibson
` (6 subsequent siblings)
10 siblings, 2 replies; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
Currently spapr_create_fdt_skel() takes a bunch of individual parameters
for various things it will put in the device tree. Some of these can
already be taken directly from sPAPRMachineState. This patch alters it so
that all of them can be taken from there, which will allow this code to
be moved away from its current caller in future.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 81 ++++++++++++++++++++++----------------------------
include/hw/ppc/spapr.h | 4 +++
2 files changed, 40 insertions(+), 45 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index b123078..da10136 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -312,16 +312,12 @@ static void add_str(GString *s, const gchar *s1)
g_string_append_len(s, s1, strlen(s1) + 1);
}
-static void *spapr_create_fdt_skel(hwaddr initrd_base,
- hwaddr initrd_size,
- hwaddr kernel_size,
- bool little_endian,
- const char *kernel_cmdline,
- uint32_t epow_irq)
+static void *spapr_create_fdt_skel(sPAPRMachineState *spapr)
{
+ MachineState *machine = MACHINE(spapr);
void *fdt;
- uint32_t start_prop = cpu_to_be32(initrd_base);
- uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
+ uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
+ uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
GString *hypertas = g_string_sized_new(256);
GString *qemu_hypertas = g_string_sized_new(256);
uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
@@ -343,11 +339,13 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
fdt = g_malloc0(FDT_MAX_SIZE);
_FDT((fdt_create(fdt, FDT_MAX_SIZE)));
- if (kernel_size) {
- _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));
+ if (spapr->kernel_size) {
+ _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
+ spapr->kernel_size)));
}
- if (initrd_size) {
- _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_size)));
+ if (spapr->initrd_size) {
+ _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
+ spapr->initrd_size)));
}
_FDT((fdt_finish_reservemap(fdt)));
@@ -397,17 +395,17 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
/* Set Form1_affinity */
_FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
- _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
+ _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
_FDT((fdt_property(fdt, "linux,initrd-start",
&start_prop, sizeof(start_prop))));
_FDT((fdt_property(fdt, "linux,initrd-end",
&end_prop, sizeof(end_prop))));
- if (kernel_size) {
+ if (spapr->kernel_size) {
uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
- cpu_to_be64(kernel_size) };
+ cpu_to_be64(spapr->kernel_size) };
_FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
- if (little_endian) {
+ if (spapr->kernel_le) {
_FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
}
}
@@ -484,7 +482,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
_FDT((fdt_end_node(fdt)));
/* event-sources */
- spapr_events_fdt_skel(fdt, epow_irq);
+ spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
/* /hypervisor node */
if (kvm_enabled()) {
@@ -1714,7 +1712,6 @@ static void ppc_spapr_init(MachineState *machine)
sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
const char *kernel_filename = machine->kernel_filename;
- const char *kernel_cmdline = machine->kernel_cmdline;
const char *initrd_filename = machine->initrd_filename;
PowerPCCPU *cpu;
PCIHostState *phb;
@@ -1725,10 +1722,7 @@ static void ppc_spapr_init(MachineState *machine)
void *rma = NULL;
hwaddr rma_alloc_size;
hwaddr node0_size = spapr_node0_size();
- uint32_t initrd_base = 0;
- long kernel_size = 0, initrd_size = 0;
long load_limit, fw_size;
- bool kernel_le = false;
char *filename;
msi_nonbroken = true;
@@ -1929,19 +1923,19 @@ static void ppc_spapr_init(MachineState *machine)
if (kernel_filename) {
uint64_t lowaddr = 0;
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
- NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
- 0, 0);
- if (kernel_size == ELF_LOAD_WRONG_ENDIAN) {
- kernel_size = load_elf(kernel_filename,
- translate_kernel_address, NULL,
- NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE,
- 0, 0);
- kernel_le = kernel_size > 0;
- }
- if (kernel_size < 0) {
- error_report("error loading %s: %s",
- kernel_filename, load_elf_strerror(kernel_size));
+ spapr->kernel_size = load_elf(kernel_filename, translate_kernel_address,
+ NULL, NULL, &lowaddr, NULL, 1,
+ PPC_ELF_MACHINE, 0, 0);
+ if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
+ spapr->kernel_size = load_elf(kernel_filename,
+ translate_kernel_address, NULL, NULL,
+ &lowaddr, NULL, 0, PPC_ELF_MACHINE,
+ 0, 0);
+ spapr->kernel_le = spapr->kernel_size > 0;
+ }
+ if (spapr->kernel_size < 0) {
+ error_report("error loading %s: %s", kernel_filename,
+ load_elf_strerror(spapr->kernel_size));
exit(1);
}
@@ -1950,17 +1944,17 @@ static void ppc_spapr_init(MachineState *machine)
/* Try to locate the initrd in the gap between the kernel
* and the firmware. Add a bit of space just in case
*/
- initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff;
- initrd_size = load_image_targphys(initrd_filename, initrd_base,
- load_limit - initrd_base);
- if (initrd_size < 0) {
+ spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size
+ + 0x1ffff) & ~0xffff;
+ spapr->initrd_size = load_image_targphys(initrd_filename,
+ spapr->initrd_base,
+ load_limit
+ - spapr->initrd_base);
+ if (spapr->initrd_size < 0) {
error_report("could not load initial ram disk '%s'",
initrd_filename);
exit(1);
}
- } else {
- initrd_base = 0;
- initrd_size = 0;
}
}
@@ -1987,10 +1981,7 @@ static void ppc_spapr_init(MachineState *machine)
&savevm_htab_handlers, spapr);
/* Prepare the device tree */
- spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size,
- kernel_size, kernel_le,
- kernel_cmdline,
- spapr->check_exception_irq);
+ spapr->fdt_skel = spapr_create_fdt_skel(spapr);
assert(spapr->fdt_skel != NULL);
/* used by RTAS */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 655ffe9..88f29a8 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -58,6 +58,10 @@ struct sPAPRMachineState {
int vrma_adjust;
ssize_t rtas_size;
void *rtas_blob;
+ long kernel_size;
+ bool kernel_le;
+ uint32_t initrd_base;
+ long initrd_size;
void *fdt_skel;
uint64_t rtc_offset; /* Now used only during incoming migration */
struct PPCTimebase tb;
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
` (3 preceding siblings ...)
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 04/11] pseries: Make spapr_create_fdt_skel() get information from machine state David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-26 18:13 ` Thomas Huth
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 06/11] pseries: Consolidate RTAS loading David Gibson
` (5 subsequent siblings)
10 siblings, 2 replies; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
Currently the pseries code builds a "skeleton" device tree at machine init
time, then adds a bunch of stuff to it at reset. Over time, more and more
logic has had to be moved from init to reset time, and there's really no
advantage to doing any of it at init time.
This patch removes the init time spapr_create_fdt_skel() and moves its
logic into the reset time spapr_build_fdt(). There's still a fairly
pointless divide between the "skeleton" logic (using libfdt serial-write
functions) and the "tweak" logic (using libfdt random access functions)
but at least it all happens at the same time, making further consolidation
easier.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 398 ++++++++++++++++++++++++-------------------------
include/hw/ppc/spapr.h | 1 -
2 files changed, 192 insertions(+), 207 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index da10136..6e1192f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -312,205 +312,6 @@ static void add_str(GString *s, const gchar *s1)
g_string_append_len(s, s1, strlen(s1) + 1);
}
-static void *spapr_create_fdt_skel(sPAPRMachineState *spapr)
-{
- MachineState *machine = MACHINE(spapr);
- void *fdt;
- uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
- uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
- GString *hypertas = g_string_sized_new(256);
- GString *qemu_hypertas = g_string_sized_new(256);
- uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
- uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
- unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
- char *buf;
-
- add_str(hypertas, "hcall-pft");
- add_str(hypertas, "hcall-term");
- add_str(hypertas, "hcall-dabr");
- add_str(hypertas, "hcall-interrupt");
- add_str(hypertas, "hcall-tce");
- add_str(hypertas, "hcall-vio");
- add_str(hypertas, "hcall-splpar");
- add_str(hypertas, "hcall-bulk");
- add_str(hypertas, "hcall-set-mode");
- add_str(qemu_hypertas, "hcall-memop1");
-
- fdt = g_malloc0(FDT_MAX_SIZE);
- _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
-
- if (spapr->kernel_size) {
- _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
- spapr->kernel_size)));
- }
- if (spapr->initrd_size) {
- _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
- spapr->initrd_size)));
- }
- _FDT((fdt_finish_reservemap(fdt)));
-
- /* Root node */
- _FDT((fdt_begin_node(fdt, "")));
- _FDT((fdt_property_string(fdt, "device_type", "chrp")));
- _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
- _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
-
- /*
- * Add info to guest to indentify which host is it being run on
- * and what is the uuid of the guest
- */
- if (kvmppc_get_host_model(&buf)) {
- _FDT((fdt_property_string(fdt, "host-model", buf)));
- g_free(buf);
- }
- if (kvmppc_get_host_serial(&buf)) {
- _FDT((fdt_property_string(fdt, "host-serial", buf)));
- g_free(buf);
- }
-
- buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
- qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
- qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
- qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
- qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
- qemu_uuid[14], qemu_uuid[15]);
-
- _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
- if (qemu_uuid_set) {
- _FDT((fdt_property_string(fdt, "system-id", buf)));
- }
- g_free(buf);
-
- if (qemu_get_vm_name()) {
- _FDT((fdt_property_string(fdt, "ibm,partition-name",
- qemu_get_vm_name())));
- }
-
- _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
- _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
-
- /* /chosen */
- _FDT((fdt_begin_node(fdt, "chosen")));
-
- /* Set Form1_affinity */
- _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
-
- _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
- _FDT((fdt_property(fdt, "linux,initrd-start",
- &start_prop, sizeof(start_prop))));
- _FDT((fdt_property(fdt, "linux,initrd-end",
- &end_prop, sizeof(end_prop))));
- if (spapr->kernel_size) {
- uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
- cpu_to_be64(spapr->kernel_size) };
-
- _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
- if (spapr->kernel_le) {
- _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
- }
- }
- if (boot_menu) {
- _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
- }
- _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
- _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
- _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
-
- _FDT((fdt_end_node(fdt)));
-
- /* RTAS */
- _FDT((fdt_begin_node(fdt, "rtas")));
-
- if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
- add_str(hypertas, "hcall-multi-tce");
- }
- _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
- hypertas->len)));
- g_string_free(hypertas, TRUE);
- _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
- qemu_hypertas->len)));
- g_string_free(qemu_hypertas, TRUE);
-
- _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
- refpoints, sizeof(refpoints))));
-
- _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
- _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
- RTAS_EVENT_SCAN_RATE)));
-
- if (msi_nonbroken) {
- _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
- }
-
- /*
- * According to PAPR, rtas ibm,os-term does not guarantee a return
- * back to the guest cpu.
- *
- * While an additional ibm,extended-os-term property indicates that
- * rtas call return will always occur. Set this property.
- */
- _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
-
- _FDT((fdt_end_node(fdt)));
-
- /* interrupt controller */
- _FDT((fdt_begin_node(fdt, "interrupt-controller")));
-
- _FDT((fdt_property_string(fdt, "device_type",
- "PowerPC-External-Interrupt-Presentation")));
- _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
- _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
- _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
- interrupt_server_ranges_prop,
- sizeof(interrupt_server_ranges_prop))));
- _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
- _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
- _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
-
- _FDT((fdt_end_node(fdt)));
-
- /* vdevice */
- _FDT((fdt_begin_node(fdt, "vdevice")));
-
- _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
- _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
- _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
- _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
- _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
- _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
-
- _FDT((fdt_end_node(fdt)));
-
- /* event-sources */
- spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
-
- /* /hypervisor node */
- if (kvm_enabled()) {
- uint8_t hypercall[16];
-
- /* indicate KVM hypercall interface */
- _FDT((fdt_begin_node(fdt, "hypervisor")));
- _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
- if (kvmppc_has_cap_fixup_hcalls()) {
- /*
- * Older KVM versions with older guest kernels were broken with the
- * magic page, don't allow the guest to map it.
- */
- if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
- sizeof(hypercall))) {
- _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
- sizeof(hypercall))));
- }
- }
- _FDT((fdt_end_node(fdt)));
- }
-
- _FDT((fdt_end_node(fdt))); /* close root node */
- _FDT((fdt_finish(fdt)));
-
- return fdt;
-}
-
static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start,
hwaddr size)
{
@@ -901,7 +702,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
hwaddr rtas_addr,
hwaddr rtas_size)
{
- MachineState *machine = MACHINE(qdev_get_machine());
+ MachineState *machine = MACHINE(spapr);
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
const char *boot_device = machine->boot_order;
int ret, i;
@@ -909,11 +710,200 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
char *bootlist;
void *fdt;
sPAPRPHBState *phb;
+ uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
+ uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
+ GString *hypertas = g_string_sized_new(256);
+ GString *qemu_hypertas = g_string_sized_new(256);
+ uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
+ uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
+ unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
+ char *buf;
+
+ add_str(hypertas, "hcall-pft");
+ add_str(hypertas, "hcall-term");
+ add_str(hypertas, "hcall-dabr");
+ add_str(hypertas, "hcall-interrupt");
+ add_str(hypertas, "hcall-tce");
+ add_str(hypertas, "hcall-vio");
+ add_str(hypertas, "hcall-splpar");
+ add_str(hypertas, "hcall-bulk");
+ add_str(hypertas, "hcall-set-mode");
+ add_str(qemu_hypertas, "hcall-memop1");
+
+ fdt = g_malloc0(FDT_MAX_SIZE);
+ _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
+
+ if (spapr->kernel_size) {
+ _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
+ spapr->kernel_size)));
+ }
+ if (spapr->initrd_size) {
+ _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
+ spapr->initrd_size)));
+ }
+ _FDT((fdt_finish_reservemap(fdt)));
+
+ /* Root node */
+ _FDT((fdt_begin_node(fdt, "")));
+ _FDT((fdt_property_string(fdt, "device_type", "chrp")));
+ _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
+ _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
+
+ /*
+ * Add info to guest to indentify which host is it being run on
+ * and what is the uuid of the guest
+ */
+ if (kvmppc_get_host_model(&buf)) {
+ _FDT((fdt_property_string(fdt, "host-model", buf)));
+ g_free(buf);
+ }
+ if (kvmppc_get_host_serial(&buf)) {
+ _FDT((fdt_property_string(fdt, "host-serial", buf)));
+ g_free(buf);
+ }
- fdt = g_malloc(FDT_MAX_SIZE);
+ buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
+ qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
+ qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
+ qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
+ qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
+ qemu_uuid[14], qemu_uuid[15]);
+
+ _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
+ if (qemu_uuid_set) {
+ _FDT((fdt_property_string(fdt, "system-id", buf)));
+ }
+ g_free(buf);
+
+ if (qemu_get_vm_name()) {
+ _FDT((fdt_property_string(fdt, "ibm,partition-name",
+ qemu_get_vm_name())));
+ }
+
+ _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
+ _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
+
+ /* /chosen */
+ _FDT((fdt_begin_node(fdt, "chosen")));
+
+ /* Set Form1_affinity */
+ _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
+
+ _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
+ _FDT((fdt_property(fdt, "linux,initrd-start",
+ &start_prop, sizeof(start_prop))));
+ _FDT((fdt_property(fdt, "linux,initrd-end",
+ &end_prop, sizeof(end_prop))));
+ if (spapr->kernel_size) {
+ uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
+ cpu_to_be64(spapr->kernel_size) };
+
+ _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
+ if (spapr->kernel_le) {
+ _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
+ }
+ }
+ if (boot_menu) {
+ _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
+ }
+ _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
+ _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
+ _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
+
+ _FDT((fdt_end_node(fdt)));
+
+ /* RTAS */
+ _FDT((fdt_begin_node(fdt, "rtas")));
+
+ if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
+ add_str(hypertas, "hcall-multi-tce");
+ }
+ _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
+ hypertas->len)));
+ g_string_free(hypertas, TRUE);
+ _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
+ qemu_hypertas->len)));
+ g_string_free(qemu_hypertas, TRUE);
+
+ _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
+ refpoints, sizeof(refpoints))));
+
+ _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
+ _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
+ RTAS_EVENT_SCAN_RATE)));
+
+ if (msi_nonbroken) {
+ _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
+ }
+
+ /*
+ * According to PAPR, rtas ibm,os-term does not guarantee a return
+ * back to the guest cpu.
+ *
+ * While an additional ibm,extended-os-term property indicates that
+ * rtas call return will always occur. Set this property.
+ */
+ _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
+
+ _FDT((fdt_end_node(fdt)));
+
+ /* interrupt controller */
+ _FDT((fdt_begin_node(fdt, "interrupt-controller")));
+
+ _FDT((fdt_property_string(fdt, "device_type",
+ "PowerPC-External-Interrupt-Presentation")));
+ _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
+ _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+ _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
+ interrupt_server_ranges_prop,
+ sizeof(interrupt_server_ranges_prop))));
+ _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
+ _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
+ _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
+
+ _FDT((fdt_end_node(fdt)));
+
+ /* vdevice */
+ _FDT((fdt_begin_node(fdt, "vdevice")));
+
+ _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
+ _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
+ _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
+ _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
+ _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
+ _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+
+ _FDT((fdt_end_node(fdt)));
+
+ /* event-sources */
+ spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
+
+ /* /hypervisor node */
+ if (kvm_enabled()) {
+ uint8_t hypercall[16];
+
+ /* indicate KVM hypercall interface */
+ _FDT((fdt_begin_node(fdt, "hypervisor")));
+ _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
+ if (kvmppc_has_cap_fixup_hcalls()) {
+ /*
+ * Older KVM versions with older guest kernels were broken with the
+ * magic page, don't allow the guest to map it.
+ */
+ if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
+ sizeof(hypercall))) {
+ _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
+ sizeof(hypercall))));
+ }
+ }
+ _FDT((fdt_end_node(fdt)));
+ }
+
+ _FDT((fdt_end_node(fdt))); /* close root node */
+ _FDT((fdt_finish(fdt)));
/* open out the base tree into a temp buffer for the final tweaks */
- _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
+ _FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
ret = spapr_populate_memory(spapr, fdt);
if (ret < 0) {
@@ -1980,10 +1970,6 @@ static void ppc_spapr_init(MachineState *machine)
register_savevm_live(NULL, "spapr/htab", -1, 1,
&savevm_htab_handlers, spapr);
- /* Prepare the device tree */
- spapr->fdt_skel = spapr_create_fdt_skel(spapr);
- assert(spapr->fdt_skel != NULL);
-
/* used by RTAS */
QTAILQ_INIT(&spapr->ccs_list);
qemu_register_reset(spapr_ccs_reset_hook, spapr);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 88f29a8..cd72586 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -62,7 +62,6 @@ struct sPAPRMachineState {
bool kernel_le;
uint32_t initrd_base;
long initrd_size;
- void *fdt_skel;
uint64_t rtc_offset; /* Now used only during incoming migration */
struct PPCTimebase tb;
bool has_graphics;
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 06/11] pseries: Consolidate RTAS loading
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
` (4 preceding siblings ...)
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-27 9:12 ` Thomas Huth
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries David Gibson
` (4 subsequent siblings)
10 siblings, 2 replies; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
At each system reset, the pseries machine needs to load RTAS, the run
time portion of the guest firmware, into the VM. This means copying
the actual RTAS code into guest memory, and also updating the device
tree so that the guest OS and boot firmware can locate it.
For historical reasons the copy and update to the device tree were in
different parts of the code. This cleanup brings them both together in
an spapr_load_rtas() function.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 3 +--
hw/ppc/spapr_rtas.c | 72 ++++++++++++++++++++++++++++----------------------
include/hw/ppc/spapr.h | 1 +
3 files changed, 43 insertions(+), 33 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6e1192f..5356f4d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1145,8 +1145,7 @@ static void ppc_spapr_reset(void)
fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
- /* Copy RTAS over */
- cpu_physical_memory_write(rtas_addr, spapr->rtas_blob, spapr->rtas_size);
+ spapr_load_rtas(spapr, fdt, rtas_addr);
rc = fdt_pack(fdt);
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index f073258..c0cb41e 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -688,37 +688,6 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
uint64_t max_hotplug_addr = spapr->hotplug_memory.base +
memory_region_size(&spapr->hotplug_memory.mr);
- ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
- if (ret < 0) {
- fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
- fdt_strerror(ret));
- return ret;
- }
-
- ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-base",
- rtas_addr);
- if (ret < 0) {
- fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
- fdt_strerror(ret));
- return ret;
- }
-
- ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
- rtas_addr);
- if (ret < 0) {
- fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
- fdt_strerror(ret));
- return ret;
- }
-
- ret = qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size",
- rtas_size);
- if (ret < 0) {
- fprintf(stderr, "Couldn't add rtas-size property: %s\n",
- fdt_strerror(ret));
- return ret;
- }
-
for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
struct rtas_call *call = &rtas_table[i];
@@ -751,6 +720,47 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
return 0;
}
+void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr)
+{
+ int rtas_node;
+ int ret;
+
+ /* Copy RTAS blob into guest RAM */
+ cpu_physical_memory_write(addr, spapr->rtas_blob, spapr->rtas_size);
+
+ ret = fdt_add_mem_rsv(fdt, addr, spapr->rtas_size);
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
+ fdt_strerror(ret));
+ exit(1);
+ }
+
+ /* Update the device tree with the blob's location */
+ rtas_node = fdt_path_offset(fdt, "/rtas");
+ assert(rtas_node >= 0);
+
+ ret = fdt_setprop_cell(fdt, rtas_node, "linux,rtas-base", addr);
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
+ fdt_strerror(ret));
+ exit(1);
+ }
+
+ ret = fdt_setprop_cell(fdt, rtas_node, "linux,rtas-entry", addr);
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
+ fdt_strerror(ret));
+ exit(1);
+ }
+
+ ret = fdt_setprop_cell(fdt, rtas_node, "rtas-size", spapr->rtas_size);
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't add rtas-size property: %s\n",
+ fdt_strerror(ret));
+ exit(1);
+ }
+}
+
static void core_rtas_register_types(void)
{
spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index cd72586..ebad34f 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -512,6 +512,7 @@ target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *sm,
uint32_t nret, target_ulong rets);
int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
hwaddr rtas_size);
+void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr);
#define SPAPR_TCE_PAGE_SHIFT 12
#define SPAPR_TCE_PAGE_SIZE (1ULL << SPAPR_TCE_PAGE_SHIFT)
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
` (5 preceding siblings ...)
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 06/11] pseries: Consolidate RTAS loading David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 5:14 ` Alexey Kardashevskiy
2016-04-27 9:19 ` Thomas Huth
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 08/11] pseries: Start using qdt library for building device tree David Gibson
` (3 subsequent siblings)
10 siblings, 2 replies; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
The flattened device tree passed to pseries guests contains a list of
reserved memory areas. Currently we construct this list early in
spapr_build_fdt() as we sequentially write out the fdt.
This will be inconvenient for upcoming cleanups, so this patch moves
the reserve map changes to the end of fdt construction. This changes
fdt_add_reservemap_entry() calls - which work when writing the fdt
sequentially to fdt_add_mem_rsv() calls used when altering the fdt in
random access mode.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 5356f4d..aef44a2 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -733,14 +733,6 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
fdt = g_malloc0(FDT_MAX_SIZE);
_FDT((fdt_create(fdt, FDT_MAX_SIZE)));
- if (spapr->kernel_size) {
- _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
- spapr->kernel_size)));
- }
- if (spapr->initrd_size) {
- _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
- spapr->initrd_size)));
- }
_FDT((fdt_finish_reservemap(fdt)));
/* Root node */
@@ -976,6 +968,15 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
}
g_free(bootlist);
+
+ /* Build memory reserve map */
+ if (spapr->kernel_size) {
+ _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
+ }
+ if (spapr->initrd_size) {
+ _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size)));
+ }
+
return fdt;
}
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 08/11] pseries: Start using qdt library for building device tree
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
` (6 preceding siblings ...)
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 4:04 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 09/11] pseries: Consolidate construction of /chosen device tree node David Gibson
` (2 subsequent siblings)
10 siblings, 1 reply; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
This starts the process of converting the pseries machine type to use
the qdt library code to build the guest's device tree instead of
working directly and awkwardly with the flattened device tree format.
For now we just convert the first section of spapr_build_fdt() which
creates a tree sequentially, so that it builds the qdt then flattens
it. This leaves a lot of code which still manipulates the fdt after
that point, but the intention is to convert those to work with the qdt
format in future.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 236 ++++++++++++++++++++++++-------------------------
hw/ppc/spapr_events.c | 19 ----
include/hw/ppc/spapr.h | 1 -
3 files changed, 117 insertions(+), 139 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index aef44a2..d04d403 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -66,6 +66,8 @@
#include "hw/compat.h"
#include "qemu/cutils.h"
+#include "qemu/qdt.h"
+
#include <libfdt.h>
/* SLOF memory layout:
@@ -710,47 +712,27 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
char *bootlist;
void *fdt;
sPAPRPHBState *phb;
- uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
- uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
- GString *hypertas = g_string_sized_new(256);
- GString *qemu_hypertas = g_string_sized_new(256);
- uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
- uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
- unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
char *buf;
+ QDTNode *root;
- add_str(hypertas, "hcall-pft");
- add_str(hypertas, "hcall-term");
- add_str(hypertas, "hcall-dabr");
- add_str(hypertas, "hcall-interrupt");
- add_str(hypertas, "hcall-tce");
- add_str(hypertas, "hcall-vio");
- add_str(hypertas, "hcall-splpar");
- add_str(hypertas, "hcall-bulk");
- add_str(hypertas, "hcall-set-mode");
- add_str(qemu_hypertas, "hcall-memop1");
-
- fdt = g_malloc0(FDT_MAX_SIZE);
- _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
+ root = qdt_new_tree();
- _FDT((fdt_finish_reservemap(fdt)));
+ /* / (root node) */
- /* Root node */
- _FDT((fdt_begin_node(fdt, "")));
- _FDT((fdt_property_string(fdt, "device_type", "chrp")));
- _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
- _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
+ qdt_setprop_string(root, "device_type", "chrp");
+ qdt_setprop_string(root, "model", "IBM pSeries (emulated by qemu)");
+ qdt_setprop_string(root, "compatible", "qemu,pseries");
/*
* Add info to guest to indentify which host is it being run on
* and what is the uuid of the guest
*/
if (kvmppc_get_host_model(&buf)) {
- _FDT((fdt_property_string(fdt, "host-model", buf)));
+ qdt_setprop_string(root, "host-model", buf);
g_free(buf);
}
if (kvmppc_get_host_serial(&buf)) {
- _FDT((fdt_property_string(fdt, "host-serial", buf)));
+ qdt_setprop_string(root, "host-serial", buf);
g_free(buf);
}
@@ -761,138 +743,154 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
qemu_uuid[14], qemu_uuid[15]);
- _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
+ qdt_setprop_string(root, "vm,uuid", buf);
if (qemu_uuid_set) {
- _FDT((fdt_property_string(fdt, "system-id", buf)));
+ qdt_setprop_string(root, "system-id", buf);
}
g_free(buf);
if (qemu_get_vm_name()) {
- _FDT((fdt_property_string(fdt, "ibm,partition-name",
- qemu_get_vm_name())));
+ qdt_setprop_string(root, "ibm,partition-name", qemu_get_vm_name());
}
- _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
- _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
+ qdt_setprop_cells(root, "#address-cells", 0x2);
+ qdt_setprop_cells(root, "#size-cells", 0x2);
/* /chosen */
- _FDT((fdt_begin_node(fdt, "chosen")));
-
- /* Set Form1_affinity */
- _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
-
- _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
- _FDT((fdt_property(fdt, "linux,initrd-start",
- &start_prop, sizeof(start_prop))));
- _FDT((fdt_property(fdt, "linux,initrd-end",
- &end_prop, sizeof(end_prop))));
- if (spapr->kernel_size) {
- uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
- cpu_to_be64(spapr->kernel_size) };
-
- _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
- if (spapr->kernel_le) {
- _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
+ {
+ QDTNode *chosen = qdt_add_subnode(root, "chosen");
+
+ /* Set Form1_affinity */
+ qdt_setprop_bytes(chosen, "ibm,architecture-vec-5",
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x80);
+
+ qdt_setprop_string(chosen, "bootargs", machine->kernel_cmdline);
+ qdt_setprop_cells(chosen, "linux,initrd-start",
+ spapr->initrd_base);
+ qdt_setprop_cells(chosen, "linux,initrd-end",
+ spapr->initrd_base + spapr->initrd_size);
+ if (spapr->kernel_size) {
+ qdt_setprop_u64s(chosen, "qemu,boot-kernel",
+ KERNEL_LOAD_ADDR, spapr->kernel_size);
+ if (spapr->kernel_le) {
+ qdt_setprop_empty(chosen, "qemu,boot-kernel-le");
+ }
}
+ if (boot_menu) {
+ qdt_setprop_cells(chosen, "qemu,boot-menu", boot_menu);
+ }
+ qdt_setprop_cells(chosen, "qemu,graphic-width", graphic_width);
+ qdt_setprop_cells(chosen, "qemu,graphic-height", graphic_height);
+ qdt_setprop_cells(chosen, "qemu,graphic-depth", graphic_depth);
}
- if (boot_menu) {
- _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
- }
- _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
- _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
- _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
-
- _FDT((fdt_end_node(fdt)));
/* RTAS */
- _FDT((fdt_begin_node(fdt, "rtas")));
+ {
+ QDTNode *rtas = qdt_add_subnode(root, "rtas");
+ GString *hypertas = g_string_sized_new(256);
+ GString *qemu_hypertas = g_string_sized_new(256);
- if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
- add_str(hypertas, "hcall-multi-tce");
- }
- _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
- hypertas->len)));
- g_string_free(hypertas, TRUE);
- _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
- qemu_hypertas->len)));
- g_string_free(qemu_hypertas, TRUE);
+ add_str(hypertas, "hcall-pft");
+ add_str(hypertas, "hcall-term");
+ add_str(hypertas, "hcall-dabr");
+ add_str(hypertas, "hcall-interrupt");
+ add_str(hypertas, "hcall-tce");
+ add_str(hypertas, "hcall-vio");
+ add_str(hypertas, "hcall-splpar");
+ add_str(hypertas, "hcall-bulk");
+ add_str(hypertas, "hcall-set-mode");
+ add_str(qemu_hypertas, "hcall-memop1");
- _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
- refpoints, sizeof(refpoints))));
+ if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
+ add_str(hypertas, "hcall-multi-tce");
+ }
+ qdt_setprop(rtas, "ibm,hypertas-functions",
+ hypertas->str, hypertas->len);
+ g_string_free(hypertas, TRUE);
+ qdt_setprop(rtas, "qemu,hypertas-functions",
+ qemu_hypertas->str, qemu_hypertas->len);
+ g_string_free(qemu_hypertas, TRUE);
- _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
- _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
- RTAS_EVENT_SCAN_RATE)));
+ qdt_setprop_cells(rtas, "ibm,associativity-reference-points", 0x4, 0x4);
- if (msi_nonbroken) {
- _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
- }
+ qdt_setprop_cells(rtas, "rtas-error-log-max", RTAS_ERROR_LOG_MAX);
+ qdt_setprop_cells(rtas, "rtas-event-scan-rate", RTAS_EVENT_SCAN_RATE);
- /*
- * According to PAPR, rtas ibm,os-term does not guarantee a return
- * back to the guest cpu.
- *
- * While an additional ibm,extended-os-term property indicates that
- * rtas call return will always occur. Set this property.
- */
- _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
+ if (msi_nonbroken) {
+ qdt_setprop_empty(rtas, "ibm,change-msix-capable");
+ }
+
+ /*
+ * According to PAPR, rtas ibm,os-term does not guarantee a
+ * return back to the guest cpu.
+ *
+ * While an additional ibm,extended-os-term property indicates
+ * that rtas call return will always occur. Set this property.
+ */
+ qdt_setprop_empty(rtas, "ibm,extended-os-term");
+ }
- _FDT((fdt_end_node(fdt)));
+ /* /interrupt controller */
+ {
+ QDTNode *xics = qdt_add_subnode(root, "interrupt-controller");
- /* interrupt controller */
- _FDT((fdt_begin_node(fdt, "interrupt-controller")));
+ qdt_setprop_string(xics, "device_type",
+ "PowerPC-External-Interrupt-Presentation");
+ qdt_setprop_string(xics, "compatible", "IBM,ppc-xicp");
+ qdt_setprop_empty(xics, "interrupt-controller");
+ qdt_setprop_cells(xics, "ibm,interrupt-server-ranges", 0, max_cpus);
+ qdt_setprop_cells(xics, "#interrupt-cells", 2);
+ qdt_set_phandle(xics, PHANDLE_XICP);
+ }
- _FDT((fdt_property_string(fdt, "device_type",
- "PowerPC-External-Interrupt-Presentation")));
- _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
- _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
- _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
- interrupt_server_ranges_prop,
- sizeof(interrupt_server_ranges_prop))));
- _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
- _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
- _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
+ /* /vdevice */
+ {
+ QDTNode *vdevice = qdt_add_subnode(root, "vdevice");
- _FDT((fdt_end_node(fdt)));
+ qdt_setprop_string(vdevice, "device_type", "vdevice");
+ qdt_setprop_string(vdevice, "compatible", "IBM,vdevice");
+ qdt_setprop_cells(vdevice, "#address-cells", 0x1);
+ qdt_setprop_cells(vdevice, "#size-cells", 0x0);
+ qdt_setprop_cells(vdevice, "#interrupt-cells", 0x2);
+ qdt_setprop_empty(vdevice, "interrupt-controller");
+ }
- /* vdevice */
- _FDT((fdt_begin_node(fdt, "vdevice")));
- _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
- _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
- _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
- _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
- _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
- _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
+ /* /event-sources */
+ {
+ QDTNode *event_sources = qdt_add_subnode(root, "event-sources");
+ QDTNode *epow;
- _FDT((fdt_end_node(fdt)));
+ qdt_setprop_empty(event_sources, "interrupt-controller");
+ qdt_setprop_cells(event_sources, "#interrupt-cells", 2);
+ qdt_setprop_cells(event_sources, "interrupt-ranges",
+ spapr->check_exception_irq, 1);
- /* event-sources */
- spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
+ epow = qdt_add_subnode(event_sources, "epow-events");
+ qdt_setprop_cells(epow, "interrupts", spapr->check_exception_irq, 0);
+ }
- /* /hypervisor node */
+ /* /hypervisor */
if (kvm_enabled()) {
- uint8_t hypercall[16];
+ QDTNode *hypervisor = qdt_add_subnode(root, "hypervisor");
/* indicate KVM hypercall interface */
- _FDT((fdt_begin_node(fdt, "hypervisor")));
- _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
+ qdt_setprop_string(hypervisor, "compatible", "linux,kvm");
if (kvmppc_has_cap_fixup_hcalls()) {
+ uint8_t hypercall[16];
/*
* Older KVM versions with older guest kernels were broken with the
* magic page, don't allow the guest to map it.
*/
if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
sizeof(hypercall))) {
- _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
- sizeof(hypercall))));
+ qdt_setprop(hypervisor, "hcall-instructions",
+ hypercall, sizeof(hypercall));
}
}
- _FDT((fdt_end_node(fdt)));
}
- _FDT((fdt_end_node(fdt))); /* close root node */
- _FDT((fdt_finish(fdt)));
+ fdt = qdt_flatten(root, FDT_MAX_SIZE, &error_fatal);
/* open out the base tree into a temp buffer for the final tweaks */
_FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 269ab7e..cce219f 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -220,25 +220,6 @@ struct hp_log_full {
} \
} while (0)
-void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
-{
- uint32_t irq_ranges[] = {cpu_to_be32(check_exception_irq), cpu_to_be32(1)};
- uint32_t interrupts[] = {cpu_to_be32(check_exception_irq), 0};
-
- _FDT((fdt_begin_node(fdt, "event-sources")));
-
- _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
- _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
- _FDT((fdt_property(fdt, "interrupt-ranges",
- irq_ranges, sizeof(irq_ranges))));
-
- _FDT((fdt_begin_node(fdt, "epow-events")));
- _FDT((fdt_property(fdt, "interrupts", interrupts, sizeof(interrupts))));
- _FDT((fdt_end_node(fdt)));
-
- _FDT((fdt_end_node(fdt)));
-}
-
static void rtas_event_log_queue(int log_type, void *data, bool exception)
{
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index ebad34f..40d3724 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -560,7 +560,6 @@ struct sPAPREventLogEntry {
};
void spapr_events_init(sPAPRMachineState *sm);
-void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
int spapr_h_cas_compose_response(sPAPRMachineState *sm,
target_ulong addr, target_ulong size,
bool cpu_update, bool memory_update);
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 09/11] pseries: Consolidate construction of /chosen device tree node
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
` (7 preceding siblings ...)
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 08/11] pseries: Start using qdt library for building device tree David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 10/11] pseries: Consolidate construction of /rtas " David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 11/11] pseries: Remove unused callbacks from sPAPR VIO bus state David Gibson
10 siblings, 1 reply; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
For historical reasons construction of the /chosen node in the device tree
(amongst others) is split into several places. This patch brings these
pieces back together to make things clearer.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 59 ++++++++++++++++++++--------------------------
hw/ppc/spapr_vio.c | 16 +++----------
include/hw/ppc/spapr_vio.h | 2 +-
3 files changed, 30 insertions(+), 47 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d04d403..a000056 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -707,9 +707,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
MachineState *machine = MACHINE(spapr);
sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
const char *boot_device = machine->boot_order;
- int ret, i;
- size_t cb = 0;
- char *bootlist;
+ int ret;
void *fdt;
sPAPRPHBState *phb;
char *buf;
@@ -759,6 +757,8 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
/* /chosen */
{
QDTNode *chosen = qdt_add_subnode(root, "chosen");
+ char *bootlist;
+ size_t cb = 0, i;
/* Set Form1_affinity */
qdt_setprop_bytes(chosen, "ibm,architecture-vec-5",
@@ -782,6 +782,29 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
qdt_setprop_cells(chosen, "qemu,graphic-width", graphic_width);
qdt_setprop_cells(chosen, "qemu,graphic-height", graphic_height);
qdt_setprop_cells(chosen, "qemu,graphic-depth", graphic_depth);
+
+ bootlist = get_boot_devices_list(&cb, true);
+ if (cb && bootlist) {
+ for (i = 0; i < cb; i++) {
+ if (bootlist[i] == '\n') {
+ bootlist[i] = ' ';
+ }
+
+ }
+ qdt_setprop_string(chosen, "qemu,boot-list", bootlist);
+ }
+ g_free(bootlist);
+
+ if (boot_device && strlen(boot_device)) {
+ qdt_setprop_string(chosen, "qemu,boot-device", boot_device);
+ }
+
+ if (!spapr->has_graphics) {
+ char *stdout = spapr_vio_stdout_path(spapr->vio_bus);
+
+ qdt_setprop_string(chosen, "linux,stdout-path", stdout);
+ g_free(stdout);
+ }
}
/* RTAS */
@@ -933,40 +956,10 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
/* cpus */
spapr_populate_cpus_dt_node(fdt, spapr);
- bootlist = get_boot_devices_list(&cb, true);
- if (cb && bootlist) {
- int offset = fdt_path_offset(fdt, "/chosen");
- if (offset < 0) {
- exit(1);
- }
- for (i = 0; i < cb; i++) {
- if (bootlist[i] == '\n') {
- bootlist[i] = ' ';
- }
-
- }
- ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist);
- }
-
- if (boot_device && strlen(boot_device)) {
- int offset = fdt_path_offset(fdt, "/chosen");
-
- if (offset < 0) {
- exit(1);
- }
- fdt_setprop_string(fdt, offset, "qemu,boot-device", boot_device);
- }
-
- if (!spapr->has_graphics) {
- spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
- }
-
if (smc->dr_lmb_enabled) {
_FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
}
- g_free(bootlist);
-
/* Build memory reserve map */
if (spapr->kernel_size) {
_FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 8aa021f..18b07e0 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -679,28 +679,18 @@ out:
return ret;
}
-int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
+gchar *spapr_vio_stdout_path(VIOsPAPRBus *bus)
{
VIOsPAPRDevice *dev;
char *name, *path;
- int ret, offset;
dev = spapr_vty_get_default(bus);
if (!dev)
- return 0;
-
- offset = fdt_path_offset(fdt, "/chosen");
- if (offset < 0) {
- return offset;
- }
+ return NULL;
name = spapr_vio_get_dev_name(DEVICE(dev));
path = g_strdup_printf("/vdevice/%s", name);
-
- ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
-
g_free(name);
- g_free(path);
- return ret;
+ return path;
}
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index c9733e7..ea00c3b 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -82,7 +82,7 @@ struct VIOsPAPRBus {
extern VIOsPAPRBus *spapr_vio_bus_init(void);
extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
-extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus);
+gchar *spapr_vio_stdout_path(VIOsPAPRBus *bus);
extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 10/11] pseries: Consolidate construction of /rtas device tree node
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
` (8 preceding siblings ...)
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 09/11] pseries: Consolidate construction of /chosen device tree node David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 11/11] pseries: Remove unused callbacks from sPAPR VIO bus state David Gibson
10 siblings, 1 reply; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
For historical reasons construction of the /rtas node in the device tree
(amongst others) is split into several places. In particular it's split
between spapr_build_fdt() and spapr_rtas_device_tree_setup().
In fact, as well as adding the actual RTAS tokens to the device tree,
spapr_rtas_device_tree_setup() just adds the ibm,lrdr-capacity property,
which despite going in the /rtas node, doesn't have a lot to do with RTAS.
This patch consolidates the code constructing /rtas together. Most of it
goes inline (but together) into spapr_build_fdt(), and
spapr_rtas_device_tree_setup() is renamed to spapr_rtas_dt_tokens() and
now only adds the token properties.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
hw/ppc/spapr.c | 18 +++++++++++-------
hw/ppc/spapr_rtas.c | 32 ++------------------------------
include/hw/ppc/spapr.h | 4 ++--
3 files changed, 15 insertions(+), 39 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a000056..f52add7 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -807,11 +807,13 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
}
}
- /* RTAS */
+ /* /rtas */
{
QDTNode *rtas = qdt_add_subnode(root, "rtas");
GString *hypertas = g_string_sized_new(256);
GString *qemu_hypertas = g_string_sized_new(256);
+ uint64_t max_hotplug_addr = spapr->hotplug_memory.base
+ + memory_region_size(&spapr->hotplug_memory.mr);
add_str(hypertas, "hcall-pft");
add_str(hypertas, "hcall-term");
@@ -851,6 +853,14 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
* that rtas call return will always occur. Set this property.
*/
qdt_setprop_empty(rtas, "ibm,extended-os-term");
+
+ qdt_setprop_cells(rtas, "ibm,lrdr-capacity",
+ max_hotplug_addr >> 32,
+ max_hotplug_addr & 0xffffffff,
+ 0, SPAPR_MEMORY_BLOCK_SIZE,
+ max_cpus / smp_threads);
+
+ spapr_rtas_dt_tokens(rtas);
}
/* /interrupt controller */
@@ -947,12 +957,6 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
exit(1);
}
- /* RTAS */
- ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
- if (ret < 0) {
- fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
- }
-
/* cpus */
spapr_populate_cpus_dt_node(fdt, spapr);
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index c0cb41e..806a7b0 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -677,16 +677,9 @@ void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
rtas_table[token].fn = fn;
}
-int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
- hwaddr rtas_size)
+void spapr_rtas_dt_tokens(QDTNode *node)
{
- int ret;
int i;
- uint32_t lrdr_capacity[5];
- MachineState *machine = MACHINE(qdev_get_machine());
- sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
- uint64_t max_hotplug_addr = spapr->hotplug_memory.base +
- memory_region_size(&spapr->hotplug_memory.mr);
for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
struct rtas_call *call = &rtas_table[i];
@@ -695,29 +688,8 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
continue;
}
- ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name,
- i + RTAS_TOKEN_BASE);
- if (ret < 0) {
- fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
- call->name, fdt_strerror(ret));
- return ret;
- }
-
+ qdt_setprop_cells(node, call->name, i + RTAS_TOKEN_BASE);
}
-
- lrdr_capacity[0] = cpu_to_be32(max_hotplug_addr >> 32);
- lrdr_capacity[1] = cpu_to_be32(max_hotplug_addr & 0xffffffff);
- lrdr_capacity[2] = 0;
- lrdr_capacity[3] = cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE);
- lrdr_capacity[4] = cpu_to_be32(max_cpus/smp_threads);
- ret = qemu_fdt_setprop(fdt, "/rtas", "ibm,lrdr-capacity", lrdr_capacity,
- sizeof(lrdr_capacity));
- if (ret < 0) {
- fprintf(stderr, "Couldn't add ibm,lrdr-capacity rtas property\n");
- return ret;
- }
-
- return 0;
}
void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr)
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 40d3724..1e609a0 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -6,6 +6,7 @@
#include "hw/ppc/xics.h"
#include "hw/ppc/spapr_drc.h"
#include "hw/mem/pc-dimm.h"
+#include "qemu/qdt.h"
struct VIOsPAPRBus;
struct sPAPRPHBState;
@@ -510,8 +511,7 @@ void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn);
target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *sm,
uint32_t token, uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets);
-int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
- hwaddr rtas_size);
+void spapr_rtas_dt_tokens(QDTNode *node);
void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr);
#define SPAPR_TCE_PAGE_SHIFT 12
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [Qemu-devel] [RFC for-2.7 11/11] pseries: Remove unused callbacks from sPAPR VIO bus state
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
` (9 preceding siblings ...)
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 10/11] pseries: Consolidate construction of /rtas " David Gibson
@ 2016-04-20 2:33 ` David Gibson
2016-04-21 5:31 ` Alexey Kardashevskiy
10 siblings, 1 reply; 44+ messages in thread
From: David Gibson @ 2016-04-20 2:33 UTC (permalink / raw)
To: agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel, David Gibson
The VIOsPAPRBus structure has some callback pointers in it which aren't
used anywhere in the code. It's not clear exactly why they were there in
the first place, but they certainly have no function now.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
include/hw/ppc/spapr_vio.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index ea00c3b..380fe4f 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -75,8 +75,6 @@ struct VIOsPAPRDevice {
struct VIOsPAPRBus {
BusState bus;
uint32_t next_reg;
- int (*init)(VIOsPAPRDevice *dev);
- int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
};
extern VIOsPAPRBus *spapr_vio_bus_init(void);
--
2.5.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 02/11] pseries: Split device tree construction from device tree load
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 02/11] pseries: Split device tree construction from device tree load David Gibson
@ 2016-04-20 18:15 ` Thomas Huth
2016-04-21 5:31 ` Alexey Kardashevskiy
1 sibling, 0 replies; 44+ messages in thread
From: Thomas Huth @ 2016-04-20 18:15 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel
On 20.04.2016 04:33, David Gibson wrote:
> spapr_finalize_fdt() both finishes building the device tree for the guest
> and loads it into guest memory. For future cleanups, it's going to be
> more convenient to do these two things separately, so split them apart.
> The loading portion is pretty trivial, so we move it inline into the
> caller, ppc_spapr_reset().
>
> We also rename spapr_finalize_fdt(), because the current name is going to
> become inaccurate.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> hw/ppc/spapr.c | 41 ++++++++++++++++++++++-------------------
> 1 file changed, 22 insertions(+), 19 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index feaab08..26b95ce 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -899,10 +899,9 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
> return 0;
> }
>
> -static void spapr_finalize_fdt(sPAPRMachineState *spapr,
> - hwaddr fdt_addr,
> - hwaddr rtas_addr,
> - hwaddr rtas_size)
> +static void *spapr_build_fdt(sPAPRMachineState *spapr,
> + hwaddr rtas_addr,
> + hwaddr rtas_size)
> {
> MachineState *machine = MACHINE(qdev_get_machine());
> sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
> @@ -988,19 +987,8 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr,
> _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
> }
>
> - _FDT((fdt_pack(fdt)));
> -
> - if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
> - error_report("FDT too big ! 0x%x bytes (max is 0x%x)",
> - fdt_totalsize(fdt), FDT_MAX_SIZE);
> - exit(1);
> - }
> -
> - qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
> - cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
> -
> g_free(bootlist);
> - g_free(fdt);
> + return fdt;
> }
>
> static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
> @@ -1138,6 +1126,8 @@ static void ppc_spapr_reset(void)
> sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
> PowerPCCPU *first_ppc_cpu;
> uint32_t rtas_limit;
> + void *fdt;
> + int rc;
>
> /* Check for unknown sysbus devices */
> foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);
> @@ -1164,14 +1154,27 @@ static void ppc_spapr_reset(void)
> spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
> spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
>
> - /* Load the fdt */
> - spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
> - spapr->rtas_size);
> + fdt = spapr_build_fdt(spapr, spapr->rtas_addr, spapr->rtas_size);
>
> /* Copy RTAS over */
> cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob,
> spapr->rtas_size);
>
> + rc = fdt_pack(fdt);
> +
> + /* Should only fail if we've built a corrupted tree */
> + assert(rc == 0);
> +
> + if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
> + error_report("FDT too big ! 0x%x bytes (max is 0x%x)",
> + fdt_totalsize(fdt), FDT_MAX_SIZE);
> + exit(1);
> + }
> +
> + /* Load the fdt */
> + qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
> + cpu_physical_memory_write(spapr->fdt_addr, fdt, fdt_totalsize(fdt));
> +
> /* Set up the entry state */
> first_ppc_cpu = POWERPC_CPU(first_cpu);
> first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
Looks good.
Reviewed-by: Thomas Huth <thuth@redhat.com>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 03/11] pseries: Remove rtas_addr and fdt_addr fields from machinestate
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 03/11] pseries: Remove rtas_addr and fdt_addr fields from machinestate David Gibson
@ 2016-04-20 18:19 ` Thomas Huth
2016-04-21 5:32 ` Alexey Kardashevskiy
1 sibling, 0 replies; 44+ messages in thread
From: Thomas Huth @ 2016-04-20 18:19 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel
On 20.04.2016 04:33, David Gibson wrote:
> These values are used only within ppc_spapr_reset(), so just change them
> to local variables.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> hw/ppc/spapr.c | 14 +++++++-------
> include/hw/ppc/spapr.h | 1 -
> 2 files changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 26b95ce..b123078 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1126,6 +1126,7 @@ static void ppc_spapr_reset(void)
> sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
> PowerPCCPU *first_ppc_cpu;
> uint32_t rtas_limit;
> + hwaddr rtas_addr, fdt_addr;
> void *fdt;
> int rc;
>
> @@ -1151,14 +1152,13 @@ static void ppc_spapr_reset(void)
> * processed with 32-bit real mode code if necessary
> */
> rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR);
> - spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
> - spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
> + rtas_addr = rtas_limit - RTAS_MAX_SIZE;
> + fdt_addr = rtas_addr - FDT_MAX_SIZE;
>
> - fdt = spapr_build_fdt(spapr, spapr->rtas_addr, spapr->rtas_size);
> + fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
>
> /* Copy RTAS over */
> - cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob,
> - spapr->rtas_size);
> + cpu_physical_memory_write(rtas_addr, spapr->rtas_blob, spapr->rtas_size);
>
> rc = fdt_pack(fdt);
>
> @@ -1173,11 +1173,11 @@ static void ppc_spapr_reset(void)
>
> /* Load the fdt */
> qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
> - cpu_physical_memory_write(spapr->fdt_addr, fdt, fdt_totalsize(fdt));
> + cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
>
> /* Set up the entry state */
> first_ppc_cpu = POWERPC_CPU(first_cpu);
> - first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
> + first_ppc_cpu->env.gpr[3] = fdt_addr;
> first_ppc_cpu->env.gpr[5] = 0;
> first_cpu->halted = 0;
> first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT;
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 815d5ee..655ffe9 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -56,7 +56,6 @@ struct sPAPRMachineState {
> uint32_t htab_shift;
> hwaddr rma_size;
> int vrma_adjust;
> - hwaddr fdt_addr, rtas_addr;
> ssize_t rtas_size;
> void *rtas_blob;
> void *fdt_skel;
>
Reviewed-by: Thomas Huth <thuth@redhat.com>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 08/11] pseries: Start using qdt library for building device tree
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 08/11] pseries: Start using qdt library for building device tree David Gibson
@ 2016-04-21 4:04 ` Alexey Kardashevskiy
2016-04-27 6:13 ` David Gibson
0 siblings, 1 reply; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 4:04 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> This starts the process of converting the pseries machine type to use
> the qdt library code to build the guest's device tree instead of
> working directly and awkwardly with the flattened device tree format.
>
> For now we just convert the first section of spapr_build_fdt() which
> creates a tree sequentially, so that it builds the qdt then flattens
> it. This leaves a lot of code which still manipulates the fdt after
> that point, but the intention is to convert those to work with the qdt
> format in future.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
9 patches or 11 look good as they do one right thing at the time.
But this one does:
1. replace _FDT() with qdt_setprop_xxx
2. "consolidates" spapr_events_fdt_skel() (other code movements got own
patches but not this one)
3. moves bits around like the hyperrtas property composer.
This all makes it harder to verify that you have not lost anything in
transition...
I'd also expect this patch to be the second (right after "qdt:
IEEE1275-style device tree utility code") or after all "consolidation"
patches (this would make even more sense), and this patch would convert all
_FDTs, and then remove _FDT() macro. Or "in future" from the commit log
means "nearest future"? :)
btw after all these device tree rendering code gathered in one place - how
many of the original justification points are still valid? Persistent
handles or being slow should not be problems anymore (as it is sequential
device tree rendering, without reordering).
> ---
> hw/ppc/spapr.c | 236 ++++++++++++++++++++++++-------------------------
> hw/ppc/spapr_events.c | 19 ----
> include/hw/ppc/spapr.h | 1 -
> 3 files changed, 117 insertions(+), 139 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index aef44a2..d04d403 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -66,6 +66,8 @@
> #include "hw/compat.h"
> #include "qemu/cutils.h"
>
> +#include "qemu/qdt.h"
> +
> #include <libfdt.h>
>
> /* SLOF memory layout:
> @@ -710,47 +712,27 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> char *bootlist;
> void *fdt;
> sPAPRPHBState *phb;
> - uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
> - uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
> - GString *hypertas = g_string_sized_new(256);
> - GString *qemu_hypertas = g_string_sized_new(256);
> - uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
> - uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
> - unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
> char *buf;
> + QDTNode *root;
>
> - add_str(hypertas, "hcall-pft");
> - add_str(hypertas, "hcall-term");
> - add_str(hypertas, "hcall-dabr");
> - add_str(hypertas, "hcall-interrupt");
> - add_str(hypertas, "hcall-tce");
> - add_str(hypertas, "hcall-vio");
> - add_str(hypertas, "hcall-splpar");
> - add_str(hypertas, "hcall-bulk");
> - add_str(hypertas, "hcall-set-mode");
> - add_str(qemu_hypertas, "hcall-memop1");
> -
> - fdt = g_malloc0(FDT_MAX_SIZE);
> - _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
> + root = qdt_new_tree();
>
> - _FDT((fdt_finish_reservemap(fdt)));
> + /* / (root node) */
>
> - /* Root node */
> - _FDT((fdt_begin_node(fdt, "")));
> - _FDT((fdt_property_string(fdt, "device_type", "chrp")));
> - _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
> - _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
> + qdt_setprop_string(root, "device_type", "chrp");
> + qdt_setprop_string(root, "model", "IBM pSeries (emulated by qemu)");
> + qdt_setprop_string(root, "compatible", "qemu,pseries");
>
> /*
> * Add info to guest to indentify which host is it being run on
> * and what is the uuid of the guest
> */
> if (kvmppc_get_host_model(&buf)) {
> - _FDT((fdt_property_string(fdt, "host-model", buf)));
> + qdt_setprop_string(root, "host-model", buf);
> g_free(buf);
> }
> if (kvmppc_get_host_serial(&buf)) {
> - _FDT((fdt_property_string(fdt, "host-serial", buf)));
> + qdt_setprop_string(root, "host-serial", buf);
> g_free(buf);
> }
>
> @@ -761,138 +743,154 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
> qemu_uuid[14], qemu_uuid[15]);
>
> - _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
> + qdt_setprop_string(root, "vm,uuid", buf);
> if (qemu_uuid_set) {
> - _FDT((fdt_property_string(fdt, "system-id", buf)));
> + qdt_setprop_string(root, "system-id", buf);
> }
> g_free(buf);
>
> if (qemu_get_vm_name()) {
> - _FDT((fdt_property_string(fdt, "ibm,partition-name",
> - qemu_get_vm_name())));
> + qdt_setprop_string(root, "ibm,partition-name", qemu_get_vm_name());
> }
>
> - _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
> - _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
> + qdt_setprop_cells(root, "#address-cells", 0x2);
> + qdt_setprop_cells(root, "#size-cells", 0x2);
>
> /* /chosen */
> - _FDT((fdt_begin_node(fdt, "chosen")));
> -
> - /* Set Form1_affinity */
> - _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
> -
> - _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
> - _FDT((fdt_property(fdt, "linux,initrd-start",
> - &start_prop, sizeof(start_prop))));
> - _FDT((fdt_property(fdt, "linux,initrd-end",
> - &end_prop, sizeof(end_prop))));
> - if (spapr->kernel_size) {
> - uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
> - cpu_to_be64(spapr->kernel_size) };
> -
> - _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
> - if (spapr->kernel_le) {
> - _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
> + {
> + QDTNode *chosen = qdt_add_subnode(root, "chosen");
> +
> + /* Set Form1_affinity */
> + qdt_setprop_bytes(chosen, "ibm,architecture-vec-5",
> + 0x0, 0x0, 0x0, 0x0, 0x0, 0x80);
> +
> + qdt_setprop_string(chosen, "bootargs", machine->kernel_cmdline);
> + qdt_setprop_cells(chosen, "linux,initrd-start",
> + spapr->initrd_base);
> + qdt_setprop_cells(chosen, "linux,initrd-end",
> + spapr->initrd_base + spapr->initrd_size);
> + if (spapr->kernel_size) {
> + qdt_setprop_u64s(chosen, "qemu,boot-kernel",
> + KERNEL_LOAD_ADDR, spapr->kernel_size);
> + if (spapr->kernel_le) {
> + qdt_setprop_empty(chosen, "qemu,boot-kernel-le");
> + }
> }
> + if (boot_menu) {
> + qdt_setprop_cells(chosen, "qemu,boot-menu", boot_menu);
> + }
> + qdt_setprop_cells(chosen, "qemu,graphic-width", graphic_width);
> + qdt_setprop_cells(chosen, "qemu,graphic-height", graphic_height);
> + qdt_setprop_cells(chosen, "qemu,graphic-depth", graphic_depth);
> }
> - if (boot_menu) {
> - _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
> - }
> - _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
> - _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
> - _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
> -
> - _FDT((fdt_end_node(fdt)));
>
> /* RTAS */
> - _FDT((fdt_begin_node(fdt, "rtas")));
> + {
> + QDTNode *rtas = qdt_add_subnode(root, "rtas");
> + GString *hypertas = g_string_sized_new(256);
> + GString *qemu_hypertas = g_string_sized_new(256);
>
> - if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> - add_str(hypertas, "hcall-multi-tce");
> - }
> - _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
> - hypertas->len)));
> - g_string_free(hypertas, TRUE);
> - _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
> - qemu_hypertas->len)));
> - g_string_free(qemu_hypertas, TRUE);
> + add_str(hypertas, "hcall-pft");
> + add_str(hypertas, "hcall-term");
> + add_str(hypertas, "hcall-dabr");
> + add_str(hypertas, "hcall-interrupt");
> + add_str(hypertas, "hcall-tce");
> + add_str(hypertas, "hcall-vio");
> + add_str(hypertas, "hcall-splpar");
> + add_str(hypertas, "hcall-bulk");
> + add_str(hypertas, "hcall-set-mode");
> + add_str(qemu_hypertas, "hcall-memop1");
>
> - _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
> - refpoints, sizeof(refpoints))));
> + if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> + add_str(hypertas, "hcall-multi-tce");
> + }
> + qdt_setprop(rtas, "ibm,hypertas-functions",
> + hypertas->str, hypertas->len);
> + g_string_free(hypertas, TRUE);
> + qdt_setprop(rtas, "qemu,hypertas-functions",
> + qemu_hypertas->str, qemu_hypertas->len);
> + g_string_free(qemu_hypertas, TRUE);
>
> - _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
> - _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
> - RTAS_EVENT_SCAN_RATE)));
> + qdt_setprop_cells(rtas, "ibm,associativity-reference-points", 0x4, 0x4);
>
> - if (msi_nonbroken) {
> - _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
> - }
> + qdt_setprop_cells(rtas, "rtas-error-log-max", RTAS_ERROR_LOG_MAX);
> + qdt_setprop_cells(rtas, "rtas-event-scan-rate", RTAS_EVENT_SCAN_RATE);
>
> - /*
> - * According to PAPR, rtas ibm,os-term does not guarantee a return
> - * back to the guest cpu.
> - *
> - * While an additional ibm,extended-os-term property indicates that
> - * rtas call return will always occur. Set this property.
> - */
> - _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
> + if (msi_nonbroken) {
> + qdt_setprop_empty(rtas, "ibm,change-msix-capable");
> + }
> +
> + /*
> + * According to PAPR, rtas ibm,os-term does not guarantee a
> + * return back to the guest cpu.
> + *
> + * While an additional ibm,extended-os-term property indicates
> + * that rtas call return will always occur. Set this property.
> + */
> + qdt_setprop_empty(rtas, "ibm,extended-os-term");
> + }
>
> - _FDT((fdt_end_node(fdt)));
> + /* /interrupt controller */
> + {
> + QDTNode *xics = qdt_add_subnode(root, "interrupt-controller");
>
> - /* interrupt controller */
> - _FDT((fdt_begin_node(fdt, "interrupt-controller")));
> + qdt_setprop_string(xics, "device_type",
> + "PowerPC-External-Interrupt-Presentation");
> + qdt_setprop_string(xics, "compatible", "IBM,ppc-xicp");
> + qdt_setprop_empty(xics, "interrupt-controller");
> + qdt_setprop_cells(xics, "ibm,interrupt-server-ranges", 0, max_cpus);
> + qdt_setprop_cells(xics, "#interrupt-cells", 2);
> + qdt_set_phandle(xics, PHANDLE_XICP);
> + }
>
> - _FDT((fdt_property_string(fdt, "device_type",
> - "PowerPC-External-Interrupt-Presentation")));
> - _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
> - _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> - _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
> - interrupt_server_ranges_prop,
> - sizeof(interrupt_server_ranges_prop))));
> - _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> - _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
> - _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
> + /* /vdevice */
> + {
> + QDTNode *vdevice = qdt_add_subnode(root, "vdevice");
>
> - _FDT((fdt_end_node(fdt)));
> + qdt_setprop_string(vdevice, "device_type", "vdevice");
> + qdt_setprop_string(vdevice, "compatible", "IBM,vdevice");
> + qdt_setprop_cells(vdevice, "#address-cells", 0x1);
> + qdt_setprop_cells(vdevice, "#size-cells", 0x0);
> + qdt_setprop_cells(vdevice, "#interrupt-cells", 0x2);
> + qdt_setprop_empty(vdevice, "interrupt-controller");
> + }
>
> - /* vdevice */
> - _FDT((fdt_begin_node(fdt, "vdevice")));
>
> - _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
> - _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
> - _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
> - _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
> - _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
> - _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> + /* /event-sources */
> + {
> + QDTNode *event_sources = qdt_add_subnode(root, "event-sources");
> + QDTNode *epow;
>
> - _FDT((fdt_end_node(fdt)));
> + qdt_setprop_empty(event_sources, "interrupt-controller");
> + qdt_setprop_cells(event_sources, "#interrupt-cells", 2);
> + qdt_setprop_cells(event_sources, "interrupt-ranges",
> + spapr->check_exception_irq, 1);
>
> - /* event-sources */
> - spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
> + epow = qdt_add_subnode(event_sources, "epow-events");
> + qdt_setprop_cells(epow, "interrupts", spapr->check_exception_irq, 0);
> + }
>
> - /* /hypervisor node */
> + /* /hypervisor */
> if (kvm_enabled()) {
> - uint8_t hypercall[16];
> + QDTNode *hypervisor = qdt_add_subnode(root, "hypervisor");
>
> /* indicate KVM hypercall interface */
> - _FDT((fdt_begin_node(fdt, "hypervisor")));
> - _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
> + qdt_setprop_string(hypervisor, "compatible", "linux,kvm");
> if (kvmppc_has_cap_fixup_hcalls()) {
> + uint8_t hypercall[16];
> /*
> * Older KVM versions with older guest kernels were broken with the
> * magic page, don't allow the guest to map it.
> */
> if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
> sizeof(hypercall))) {
> - _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
> - sizeof(hypercall))));
> + qdt_setprop(hypervisor, "hcall-instructions",
> + hypercall, sizeof(hypercall));
> }
> }
> - _FDT((fdt_end_node(fdt)));
> }
>
> - _FDT((fdt_end_node(fdt))); /* close root node */
> - _FDT((fdt_finish(fdt)));
> + fdt = qdt_flatten(root, FDT_MAX_SIZE, &error_fatal);
>
> /* open out the base tree into a temp buffer for the final tweaks */
> _FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
> diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
> index 269ab7e..cce219f 100644
> --- a/hw/ppc/spapr_events.c
> +++ b/hw/ppc/spapr_events.c
> @@ -220,25 +220,6 @@ struct hp_log_full {
> } \
> } while (0)
>
> -void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
> -{
> - uint32_t irq_ranges[] = {cpu_to_be32(check_exception_irq), cpu_to_be32(1)};
> - uint32_t interrupts[] = {cpu_to_be32(check_exception_irq), 0};
> -
> - _FDT((fdt_begin_node(fdt, "event-sources")));
> -
> - _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> - _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> - _FDT((fdt_property(fdt, "interrupt-ranges",
> - irq_ranges, sizeof(irq_ranges))));
> -
> - _FDT((fdt_begin_node(fdt, "epow-events")));
> - _FDT((fdt_property(fdt, "interrupts", interrupts, sizeof(interrupts))));
> - _FDT((fdt_end_node(fdt)));
> -
> - _FDT((fdt_end_node(fdt)));
> -}
> -
> static void rtas_event_log_queue(int log_type, void *data, bool exception)
> {
> sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index ebad34f..40d3724 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -560,7 +560,6 @@ struct sPAPREventLogEntry {
> };
>
> void spapr_events_init(sPAPRMachineState *sm);
> -void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
> int spapr_h_cas_compose_response(sPAPRMachineState *sm,
> target_ulong addr, target_ulong size,
> bool cpu_update, bool memory_update);
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries David Gibson
@ 2016-04-21 5:14 ` Alexey Kardashevskiy
2016-04-21 5:52 ` David Gibson
2016-04-27 9:19 ` Thomas Huth
1 sibling, 1 reply; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:14 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> The flattened device tree passed to pseries guests contains a list of
> reserved memory areas. Currently we construct this list early in
> spapr_build_fdt() as we sequentially write out the fdt.
>
> This will be inconvenient for upcoming cleanups, so this patch moves
> the reserve map changes to the end of fdt construction. This changes
> fdt_add_reservemap_entry() calls - which work when writing the fdt
> sequentially to fdt_add_mem_rsv() calls used when altering the fdt in
> random access mode.
Looks to me like the real reason for this move is that new qdt_setprop_xxx
API does not support memory reserve map yet. Will it, when? In general,
when do you plan to get rid of _FDT()?
Anyway,
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> hw/ppc/spapr.c | 17 +++++++++--------
> 1 file changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 5356f4d..aef44a2 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -733,14 +733,6 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> fdt = g_malloc0(FDT_MAX_SIZE);
> _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
>
> - if (spapr->kernel_size) {
> - _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
> - spapr->kernel_size)));
> - }
> - if (spapr->initrd_size) {
> - _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
> - spapr->initrd_size)));
> - }
> _FDT((fdt_finish_reservemap(fdt)));
>
> /* Root node */
> @@ -976,6 +968,15 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> }
>
> g_free(bootlist);
> +
> + /* Build memory reserve map */
> + if (spapr->kernel_size) {
> + _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
> + }
> + if (spapr->initrd_size) {
> + _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size)));
> + }
> +
> return fdt;
> }
>
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 11/11] pseries: Remove unused callbacks from sPAPR VIO bus state
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 11/11] pseries: Remove unused callbacks from sPAPR VIO bus state David Gibson
@ 2016-04-21 5:31 ` Alexey Kardashevskiy
2016-04-27 6:22 ` David Gibson
0 siblings, 1 reply; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:31 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> The VIOsPAPRBus structure has some callback pointers in it which aren't
> used anywhere in the code. It's not clear exactly why they were there in
> the first place, but they certainly have no function now.
It is clear - incorrect QOM'fication in 3954d33ab7f82f5a5 when parts of
VIOsPAPRDeviceInfo became parts of VIOsPAPRBus, you can adjust the commit
log :)
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> include/hw/ppc/spapr_vio.h | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
> index ea00c3b..380fe4f 100644
> --- a/include/hw/ppc/spapr_vio.h
> +++ b/include/hw/ppc/spapr_vio.h
> @@ -75,8 +75,6 @@ struct VIOsPAPRDevice {
> struct VIOsPAPRBus {
> BusState bus;
> uint32_t next_reg;
> - int (*init)(VIOsPAPRDevice *dev);
> - int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
> };
>
> extern VIOsPAPRBus *spapr_vio_bus_init(void);
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 02/11] pseries: Split device tree construction from device tree load
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 02/11] pseries: Split device tree construction from device tree load David Gibson
2016-04-20 18:15 ` Thomas Huth
@ 2016-04-21 5:31 ` Alexey Kardashevskiy
1 sibling, 0 replies; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:31 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> spapr_finalize_fdt() both finishes building the device tree for the guest
> and loads it into guest memory. For future cleanups, it's going to be
> more convenient to do these two things separately, so split them apart.
> The loading portion is pretty trivial, so we move it inline into the
> caller, ppc_spapr_reset().
>
> We also rename spapr_finalize_fdt(), because the current name is going to
> become inaccurate.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> hw/ppc/spapr.c | 41 ++++++++++++++++++++++-------------------
> 1 file changed, 22 insertions(+), 19 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index feaab08..26b95ce 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -899,10 +899,9 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
> return 0;
> }
>
> -static void spapr_finalize_fdt(sPAPRMachineState *spapr,
> - hwaddr fdt_addr,
> - hwaddr rtas_addr,
> - hwaddr rtas_size)
> +static void *spapr_build_fdt(sPAPRMachineState *spapr,
> + hwaddr rtas_addr,
> + hwaddr rtas_size)
> {
> MachineState *machine = MACHINE(qdev_get_machine());
> sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
> @@ -988,19 +987,8 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr,
> _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
> }
>
> - _FDT((fdt_pack(fdt)));
> -
> - if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
> - error_report("FDT too big ! 0x%x bytes (max is 0x%x)",
> - fdt_totalsize(fdt), FDT_MAX_SIZE);
> - exit(1);
> - }
> -
> - qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
> - cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
> -
> g_free(bootlist);
> - g_free(fdt);
> + return fdt;
> }
>
> static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
> @@ -1138,6 +1126,8 @@ static void ppc_spapr_reset(void)
> sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
> PowerPCCPU *first_ppc_cpu;
> uint32_t rtas_limit;
> + void *fdt;
> + int rc;
>
> /* Check for unknown sysbus devices */
> foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);
> @@ -1164,14 +1154,27 @@ static void ppc_spapr_reset(void)
> spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
> spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
>
> - /* Load the fdt */
> - spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
> - spapr->rtas_size);
> + fdt = spapr_build_fdt(spapr, spapr->rtas_addr, spapr->rtas_size);
>
> /* Copy RTAS over */
> cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob,
> spapr->rtas_size);
>
> + rc = fdt_pack(fdt);
> +
> + /* Should only fail if we've built a corrupted tree */
> + assert(rc == 0);
> +
> + if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
> + error_report("FDT too big ! 0x%x bytes (max is 0x%x)",
> + fdt_totalsize(fdt), FDT_MAX_SIZE);
> + exit(1);
> + }
> +
> + /* Load the fdt */
> + qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
> + cpu_physical_memory_write(spapr->fdt_addr, fdt, fdt_totalsize(fdt));
> +
> /* Set up the entry state */
> first_ppc_cpu = POWERPC_CPU(first_cpu);
> first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 03/11] pseries: Remove rtas_addr and fdt_addr fields from machinestate
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 03/11] pseries: Remove rtas_addr and fdt_addr fields from machinestate David Gibson
2016-04-20 18:19 ` Thomas Huth
@ 2016-04-21 5:32 ` Alexey Kardashevskiy
1 sibling, 0 replies; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:32 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> These values are used only within ppc_spapr_reset(), so just change them
> to local variables.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> hw/ppc/spapr.c | 14 +++++++-------
> include/hw/ppc/spapr.h | 1 -
> 2 files changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 26b95ce..b123078 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1126,6 +1126,7 @@ static void ppc_spapr_reset(void)
> sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
> PowerPCCPU *first_ppc_cpu;
> uint32_t rtas_limit;
> + hwaddr rtas_addr, fdt_addr;
> void *fdt;
> int rc;
>
> @@ -1151,14 +1152,13 @@ static void ppc_spapr_reset(void)
> * processed with 32-bit real mode code if necessary
> */
> rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR);
> - spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
> - spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
> + rtas_addr = rtas_limit - RTAS_MAX_SIZE;
> + fdt_addr = rtas_addr - FDT_MAX_SIZE;
>
> - fdt = spapr_build_fdt(spapr, spapr->rtas_addr, spapr->rtas_size);
> + fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
>
> /* Copy RTAS over */
> - cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob,
> - spapr->rtas_size);
> + cpu_physical_memory_write(rtas_addr, spapr->rtas_blob, spapr->rtas_size);
>
> rc = fdt_pack(fdt);
>
> @@ -1173,11 +1173,11 @@ static void ppc_spapr_reset(void)
>
> /* Load the fdt */
> qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
> - cpu_physical_memory_write(spapr->fdt_addr, fdt, fdt_totalsize(fdt));
> + cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
>
> /* Set up the entry state */
> first_ppc_cpu = POWERPC_CPU(first_cpu);
> - first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
> + first_ppc_cpu->env.gpr[3] = fdt_addr;
> first_ppc_cpu->env.gpr[5] = 0;
> first_cpu->halted = 0;
> first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT;
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 815d5ee..655ffe9 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -56,7 +56,6 @@ struct sPAPRMachineState {
> uint32_t htab_shift;
> hwaddr rma_size;
> int vrma_adjust;
> - hwaddr fdt_addr, rtas_addr;
> ssize_t rtas_size;
> void *rtas_blob;
> void *fdt_skel;
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 04/11] pseries: Make spapr_create_fdt_skel() get information from machine state
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 04/11] pseries: Make spapr_create_fdt_skel() get information from machine state David Gibson
@ 2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-26 17:41 ` Thomas Huth
1 sibling, 0 replies; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:32 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> Currently spapr_create_fdt_skel() takes a bunch of individual parameters
> for various things it will put in the device tree. Some of these can
> already be taken directly from sPAPRMachineState. This patch alters it so
> that all of them can be taken from there, which will allow this code to
> be moved away from its current caller in future.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> hw/ppc/spapr.c | 81 ++++++++++++++++++++++----------------------------
> include/hw/ppc/spapr.h | 4 +++
> 2 files changed, 40 insertions(+), 45 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index b123078..da10136 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -312,16 +312,12 @@ static void add_str(GString *s, const gchar *s1)
> g_string_append_len(s, s1, strlen(s1) + 1);
> }
>
> -static void *spapr_create_fdt_skel(hwaddr initrd_base,
> - hwaddr initrd_size,
> - hwaddr kernel_size,
> - bool little_endian,
> - const char *kernel_cmdline,
> - uint32_t epow_irq)
> +static void *spapr_create_fdt_skel(sPAPRMachineState *spapr)
> {
> + MachineState *machine = MACHINE(spapr);
> void *fdt;
> - uint32_t start_prop = cpu_to_be32(initrd_base);
> - uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
> + uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
> + uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
> GString *hypertas = g_string_sized_new(256);
> GString *qemu_hypertas = g_string_sized_new(256);
> uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
> @@ -343,11 +339,13 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
> fdt = g_malloc0(FDT_MAX_SIZE);
> _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
>
> - if (kernel_size) {
> - _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size)));
> + if (spapr->kernel_size) {
> + _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
> + spapr->kernel_size)));
> }
> - if (initrd_size) {
> - _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_size)));
> + if (spapr->initrd_size) {
> + _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
> + spapr->initrd_size)));
> }
> _FDT((fdt_finish_reservemap(fdt)));
>
> @@ -397,17 +395,17 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
> /* Set Form1_affinity */
> _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
>
> - _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline)));
> + _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
> _FDT((fdt_property(fdt, "linux,initrd-start",
> &start_prop, sizeof(start_prop))));
> _FDT((fdt_property(fdt, "linux,initrd-end",
> &end_prop, sizeof(end_prop))));
> - if (kernel_size) {
> + if (spapr->kernel_size) {
> uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
> - cpu_to_be64(kernel_size) };
> + cpu_to_be64(spapr->kernel_size) };
>
> _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
> - if (little_endian) {
> + if (spapr->kernel_le) {
> _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
> }
> }
> @@ -484,7 +482,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
> _FDT((fdt_end_node(fdt)));
>
> /* event-sources */
> - spapr_events_fdt_skel(fdt, epow_irq);
> + spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
>
> /* /hypervisor node */
> if (kvm_enabled()) {
> @@ -1714,7 +1712,6 @@ static void ppc_spapr_init(MachineState *machine)
> sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
> sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
> const char *kernel_filename = machine->kernel_filename;
> - const char *kernel_cmdline = machine->kernel_cmdline;
> const char *initrd_filename = machine->initrd_filename;
> PowerPCCPU *cpu;
> PCIHostState *phb;
> @@ -1725,10 +1722,7 @@ static void ppc_spapr_init(MachineState *machine)
> void *rma = NULL;
> hwaddr rma_alloc_size;
> hwaddr node0_size = spapr_node0_size();
> - uint32_t initrd_base = 0;
> - long kernel_size = 0, initrd_size = 0;
> long load_limit, fw_size;
> - bool kernel_le = false;
> char *filename;
>
> msi_nonbroken = true;
> @@ -1929,19 +1923,19 @@ static void ppc_spapr_init(MachineState *machine)
> if (kernel_filename) {
> uint64_t lowaddr = 0;
>
> - kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
> - NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE,
> - 0, 0);
> - if (kernel_size == ELF_LOAD_WRONG_ENDIAN) {
> - kernel_size = load_elf(kernel_filename,
> - translate_kernel_address, NULL,
> - NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE,
> - 0, 0);
> - kernel_le = kernel_size > 0;
> - }
> - if (kernel_size < 0) {
> - error_report("error loading %s: %s",
> - kernel_filename, load_elf_strerror(kernel_size));
> + spapr->kernel_size = load_elf(kernel_filename, translate_kernel_address,
> + NULL, NULL, &lowaddr, NULL, 1,
> + PPC_ELF_MACHINE, 0, 0);
> + if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
> + spapr->kernel_size = load_elf(kernel_filename,
> + translate_kernel_address, NULL, NULL,
> + &lowaddr, NULL, 0, PPC_ELF_MACHINE,
> + 0, 0);
> + spapr->kernel_le = spapr->kernel_size > 0;
> + }
> + if (spapr->kernel_size < 0) {
> + error_report("error loading %s: %s", kernel_filename,
> + load_elf_strerror(spapr->kernel_size));
> exit(1);
> }
>
> @@ -1950,17 +1944,17 @@ static void ppc_spapr_init(MachineState *machine)
> /* Try to locate the initrd in the gap between the kernel
> * and the firmware. Add a bit of space just in case
> */
> - initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff;
> - initrd_size = load_image_targphys(initrd_filename, initrd_base,
> - load_limit - initrd_base);
> - if (initrd_size < 0) {
> + spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size
> + + 0x1ffff) & ~0xffff;
> + spapr->initrd_size = load_image_targphys(initrd_filename,
> + spapr->initrd_base,
> + load_limit
> + - spapr->initrd_base);
> + if (spapr->initrd_size < 0) {
> error_report("could not load initial ram disk '%s'",
> initrd_filename);
> exit(1);
> }
> - } else {
> - initrd_base = 0;
> - initrd_size = 0;
> }
> }
>
> @@ -1987,10 +1981,7 @@ static void ppc_spapr_init(MachineState *machine)
> &savevm_htab_handlers, spapr);
>
> /* Prepare the device tree */
> - spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size,
> - kernel_size, kernel_le,
> - kernel_cmdline,
> - spapr->check_exception_irq);
> + spapr->fdt_skel = spapr_create_fdt_skel(spapr);
> assert(spapr->fdt_skel != NULL);
>
> /* used by RTAS */
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 655ffe9..88f29a8 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -58,6 +58,10 @@ struct sPAPRMachineState {
> int vrma_adjust;
> ssize_t rtas_size;
> void *rtas_blob;
> + long kernel_size;
> + bool kernel_le;
> + uint32_t initrd_base;
> + long initrd_size;
> void *fdt_skel;
> uint64_t rtc_offset; /* Now used only during incoming migration */
> struct PPCTimebase tb;
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time David Gibson
@ 2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-26 18:13 ` Thomas Huth
1 sibling, 0 replies; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:32 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> Currently the pseries code builds a "skeleton" device tree at machine init
> time, then adds a bunch of stuff to it at reset. Over time, more and more
> logic has had to be moved from init to reset time, and there's really no
> advantage to doing any of it at init time.
>
> This patch removes the init time spapr_create_fdt_skel() and moves its
> logic into the reset time spapr_build_fdt(). There's still a fairly
> pointless divide between the "skeleton" logic (using libfdt serial-write
> functions) and the "tweak" logic (using libfdt random access functions)
> but at least it all happens at the same time, making further consolidation
> easier.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> hw/ppc/spapr.c | 398 ++++++++++++++++++++++++-------------------------
> include/hw/ppc/spapr.h | 1 -
> 2 files changed, 192 insertions(+), 207 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index da10136..6e1192f 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -312,205 +312,6 @@ static void add_str(GString *s, const gchar *s1)
> g_string_append_len(s, s1, strlen(s1) + 1);
> }
>
> -static void *spapr_create_fdt_skel(sPAPRMachineState *spapr)
> -{
> - MachineState *machine = MACHINE(spapr);
> - void *fdt;
> - uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
> - uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
> - GString *hypertas = g_string_sized_new(256);
> - GString *qemu_hypertas = g_string_sized_new(256);
> - uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
> - uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
> - unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
> - char *buf;
> -
> - add_str(hypertas, "hcall-pft");
> - add_str(hypertas, "hcall-term");
> - add_str(hypertas, "hcall-dabr");
> - add_str(hypertas, "hcall-interrupt");
> - add_str(hypertas, "hcall-tce");
> - add_str(hypertas, "hcall-vio");
> - add_str(hypertas, "hcall-splpar");
> - add_str(hypertas, "hcall-bulk");
> - add_str(hypertas, "hcall-set-mode");
> - add_str(qemu_hypertas, "hcall-memop1");
> -
> - fdt = g_malloc0(FDT_MAX_SIZE);
> - _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
> -
> - if (spapr->kernel_size) {
> - _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
> - spapr->kernel_size)));
> - }
> - if (spapr->initrd_size) {
> - _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
> - spapr->initrd_size)));
> - }
> - _FDT((fdt_finish_reservemap(fdt)));
> -
> - /* Root node */
> - _FDT((fdt_begin_node(fdt, "")));
> - _FDT((fdt_property_string(fdt, "device_type", "chrp")));
> - _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
> - _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
> -
> - /*
> - * Add info to guest to indentify which host is it being run on
> - * and what is the uuid of the guest
> - */
> - if (kvmppc_get_host_model(&buf)) {
> - _FDT((fdt_property_string(fdt, "host-model", buf)));
> - g_free(buf);
> - }
> - if (kvmppc_get_host_serial(&buf)) {
> - _FDT((fdt_property_string(fdt, "host-serial", buf)));
> - g_free(buf);
> - }
> -
> - buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
> - qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
> - qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
> - qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
> - qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
> - qemu_uuid[14], qemu_uuid[15]);
> -
> - _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
> - if (qemu_uuid_set) {
> - _FDT((fdt_property_string(fdt, "system-id", buf)));
> - }
> - g_free(buf);
> -
> - if (qemu_get_vm_name()) {
> - _FDT((fdt_property_string(fdt, "ibm,partition-name",
> - qemu_get_vm_name())));
> - }
> -
> - _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
> - _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
> -
> - /* /chosen */
> - _FDT((fdt_begin_node(fdt, "chosen")));
> -
> - /* Set Form1_affinity */
> - _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
> -
> - _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
> - _FDT((fdt_property(fdt, "linux,initrd-start",
> - &start_prop, sizeof(start_prop))));
> - _FDT((fdt_property(fdt, "linux,initrd-end",
> - &end_prop, sizeof(end_prop))));
> - if (spapr->kernel_size) {
> - uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
> - cpu_to_be64(spapr->kernel_size) };
> -
> - _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
> - if (spapr->kernel_le) {
> - _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
> - }
> - }
> - if (boot_menu) {
> - _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
> - }
> - _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
> - _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
> - _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
> -
> - _FDT((fdt_end_node(fdt)));
> -
> - /* RTAS */
> - _FDT((fdt_begin_node(fdt, "rtas")));
> -
> - if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> - add_str(hypertas, "hcall-multi-tce");
> - }
> - _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
> - hypertas->len)));
> - g_string_free(hypertas, TRUE);
> - _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
> - qemu_hypertas->len)));
> - g_string_free(qemu_hypertas, TRUE);
> -
> - _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
> - refpoints, sizeof(refpoints))));
> -
> - _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
> - _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
> - RTAS_EVENT_SCAN_RATE)));
> -
> - if (msi_nonbroken) {
> - _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
> - }
> -
> - /*
> - * According to PAPR, rtas ibm,os-term does not guarantee a return
> - * back to the guest cpu.
> - *
> - * While an additional ibm,extended-os-term property indicates that
> - * rtas call return will always occur. Set this property.
> - */
> - _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
> -
> - _FDT((fdt_end_node(fdt)));
> -
> - /* interrupt controller */
> - _FDT((fdt_begin_node(fdt, "interrupt-controller")));
> -
> - _FDT((fdt_property_string(fdt, "device_type",
> - "PowerPC-External-Interrupt-Presentation")));
> - _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
> - _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> - _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
> - interrupt_server_ranges_prop,
> - sizeof(interrupt_server_ranges_prop))));
> - _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> - _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
> - _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
> -
> - _FDT((fdt_end_node(fdt)));
> -
> - /* vdevice */
> - _FDT((fdt_begin_node(fdt, "vdevice")));
> -
> - _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
> - _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
> - _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
> - _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
> - _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
> - _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> -
> - _FDT((fdt_end_node(fdt)));
> -
> - /* event-sources */
> - spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
> -
> - /* /hypervisor node */
> - if (kvm_enabled()) {
> - uint8_t hypercall[16];
> -
> - /* indicate KVM hypercall interface */
> - _FDT((fdt_begin_node(fdt, "hypervisor")));
> - _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
> - if (kvmppc_has_cap_fixup_hcalls()) {
> - /*
> - * Older KVM versions with older guest kernels were broken with the
> - * magic page, don't allow the guest to map it.
> - */
> - if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
> - sizeof(hypercall))) {
> - _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
> - sizeof(hypercall))));
> - }
> - }
> - _FDT((fdt_end_node(fdt)));
> - }
> -
> - _FDT((fdt_end_node(fdt))); /* close root node */
> - _FDT((fdt_finish(fdt)));
> -
> - return fdt;
> -}
> -
> static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start,
> hwaddr size)
> {
> @@ -901,7 +702,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> hwaddr rtas_addr,
> hwaddr rtas_size)
> {
> - MachineState *machine = MACHINE(qdev_get_machine());
> + MachineState *machine = MACHINE(spapr);
> sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
> const char *boot_device = machine->boot_order;
> int ret, i;
> @@ -909,11 +710,200 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> char *bootlist;
> void *fdt;
> sPAPRPHBState *phb;
> + uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
> + uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
> + GString *hypertas = g_string_sized_new(256);
> + GString *qemu_hypertas = g_string_sized_new(256);
> + uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
> + uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
> + unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
> + char *buf;
> +
> + add_str(hypertas, "hcall-pft");
> + add_str(hypertas, "hcall-term");
> + add_str(hypertas, "hcall-dabr");
> + add_str(hypertas, "hcall-interrupt");
> + add_str(hypertas, "hcall-tce");
> + add_str(hypertas, "hcall-vio");
> + add_str(hypertas, "hcall-splpar");
> + add_str(hypertas, "hcall-bulk");
> + add_str(hypertas, "hcall-set-mode");
> + add_str(qemu_hypertas, "hcall-memop1");
> +
> + fdt = g_malloc0(FDT_MAX_SIZE);
> + _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
> +
> + if (spapr->kernel_size) {
> + _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
> + spapr->kernel_size)));
> + }
> + if (spapr->initrd_size) {
> + _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
> + spapr->initrd_size)));
> + }
> + _FDT((fdt_finish_reservemap(fdt)));
> +
> + /* Root node */
> + _FDT((fdt_begin_node(fdt, "")));
> + _FDT((fdt_property_string(fdt, "device_type", "chrp")));
> + _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
> + _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
> +
> + /*
> + * Add info to guest to indentify which host is it being run on
> + * and what is the uuid of the guest
> + */
> + if (kvmppc_get_host_model(&buf)) {
> + _FDT((fdt_property_string(fdt, "host-model", buf)));
> + g_free(buf);
> + }
> + if (kvmppc_get_host_serial(&buf)) {
> + _FDT((fdt_property_string(fdt, "host-serial", buf)));
> + g_free(buf);
> + }
>
> - fdt = g_malloc(FDT_MAX_SIZE);
> + buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
> + qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
> + qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
> + qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
> + qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
> + qemu_uuid[14], qemu_uuid[15]);
> +
> + _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
> + if (qemu_uuid_set) {
> + _FDT((fdt_property_string(fdt, "system-id", buf)));
> + }
> + g_free(buf);
> +
> + if (qemu_get_vm_name()) {
> + _FDT((fdt_property_string(fdt, "ibm,partition-name",
> + qemu_get_vm_name())));
> + }
> +
> + _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
> + _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
> +
> + /* /chosen */
> + _FDT((fdt_begin_node(fdt, "chosen")));
> +
> + /* Set Form1_affinity */
> + _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
> +
> + _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
> + _FDT((fdt_property(fdt, "linux,initrd-start",
> + &start_prop, sizeof(start_prop))));
> + _FDT((fdt_property(fdt, "linux,initrd-end",
> + &end_prop, sizeof(end_prop))));
> + if (spapr->kernel_size) {
> + uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
> + cpu_to_be64(spapr->kernel_size) };
> +
> + _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
> + if (spapr->kernel_le) {
> + _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
> + }
> + }
> + if (boot_menu) {
> + _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
> + }
> + _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
> + _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
> + _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
> +
> + _FDT((fdt_end_node(fdt)));
> +
> + /* RTAS */
> + _FDT((fdt_begin_node(fdt, "rtas")));
> +
> + if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> + add_str(hypertas, "hcall-multi-tce");
> + }
> + _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
> + hypertas->len)));
> + g_string_free(hypertas, TRUE);
> + _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
> + qemu_hypertas->len)));
> + g_string_free(qemu_hypertas, TRUE);
> +
> + _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
> + refpoints, sizeof(refpoints))));
> +
> + _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
> + _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
> + RTAS_EVENT_SCAN_RATE)));
> +
> + if (msi_nonbroken) {
> + _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
> + }
> +
> + /*
> + * According to PAPR, rtas ibm,os-term does not guarantee a return
> + * back to the guest cpu.
> + *
> + * While an additional ibm,extended-os-term property indicates that
> + * rtas call return will always occur. Set this property.
> + */
> + _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
> +
> + _FDT((fdt_end_node(fdt)));
> +
> + /* interrupt controller */
> + _FDT((fdt_begin_node(fdt, "interrupt-controller")));
> +
> + _FDT((fdt_property_string(fdt, "device_type",
> + "PowerPC-External-Interrupt-Presentation")));
> + _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
> + _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> + _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
> + interrupt_server_ranges_prop,
> + sizeof(interrupt_server_ranges_prop))));
> + _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> + _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
> + _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
> +
> + _FDT((fdt_end_node(fdt)));
> +
> + /* vdevice */
> + _FDT((fdt_begin_node(fdt, "vdevice")));
> +
> + _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
> + _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
> + _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
> + _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
> + _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
> + _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> +
> + _FDT((fdt_end_node(fdt)));
> +
> + /* event-sources */
> + spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
> +
> + /* /hypervisor node */
> + if (kvm_enabled()) {
> + uint8_t hypercall[16];
> +
> + /* indicate KVM hypercall interface */
> + _FDT((fdt_begin_node(fdt, "hypervisor")));
> + _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
> + if (kvmppc_has_cap_fixup_hcalls()) {
> + /*
> + * Older KVM versions with older guest kernels were broken with the
> + * magic page, don't allow the guest to map it.
> + */
> + if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
> + sizeof(hypercall))) {
> + _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
> + sizeof(hypercall))));
> + }
> + }
> + _FDT((fdt_end_node(fdt)));
> + }
> +
> + _FDT((fdt_end_node(fdt))); /* close root node */
> + _FDT((fdt_finish(fdt)));
>
> /* open out the base tree into a temp buffer for the final tweaks */
> - _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
> + _FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
>
> ret = spapr_populate_memory(spapr, fdt);
> if (ret < 0) {
> @@ -1980,10 +1970,6 @@ static void ppc_spapr_init(MachineState *machine)
> register_savevm_live(NULL, "spapr/htab", -1, 1,
> &savevm_htab_handlers, spapr);
>
> - /* Prepare the device tree */
> - spapr->fdt_skel = spapr_create_fdt_skel(spapr);
> - assert(spapr->fdt_skel != NULL);
> -
> /* used by RTAS */
> QTAILQ_INIT(&spapr->ccs_list);
> qemu_register_reset(spapr_ccs_reset_hook, spapr);
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 88f29a8..cd72586 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -62,7 +62,6 @@ struct sPAPRMachineState {
> bool kernel_le;
> uint32_t initrd_base;
> long initrd_size;
> - void *fdt_skel;
> uint64_t rtc_offset; /* Now used only during incoming migration */
> struct PPCTimebase tb;
> bool has_graphics;
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 06/11] pseries: Consolidate RTAS loading
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 06/11] pseries: Consolidate RTAS loading David Gibson
@ 2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-27 9:12 ` Thomas Huth
1 sibling, 0 replies; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:32 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> At each system reset, the pseries machine needs to load RTAS, the run
> time portion of the guest firmware, into the VM. This means copying
> the actual RTAS code into guest memory, and also updating the device
> tree so that the guest OS and boot firmware can locate it.
>
> For historical reasons the copy and update to the device tree were in
> different parts of the code. This cleanup brings them both together in
> an spapr_load_rtas() function.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> hw/ppc/spapr.c | 3 +--
> hw/ppc/spapr_rtas.c | 72 ++++++++++++++++++++++++++++----------------------
> include/hw/ppc/spapr.h | 1 +
> 3 files changed, 43 insertions(+), 33 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 6e1192f..5356f4d 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1145,8 +1145,7 @@ static void ppc_spapr_reset(void)
>
> fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
>
> - /* Copy RTAS over */
> - cpu_physical_memory_write(rtas_addr, spapr->rtas_blob, spapr->rtas_size);
> + spapr_load_rtas(spapr, fdt, rtas_addr);
>
> rc = fdt_pack(fdt);
>
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index f073258..c0cb41e 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -688,37 +688,6 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
> uint64_t max_hotplug_addr = spapr->hotplug_memory.base +
> memory_region_size(&spapr->hotplug_memory.mr);
>
> - ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size);
> - if (ret < 0) {
> - fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
> - fdt_strerror(ret));
> - return ret;
> - }
> -
> - ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-base",
> - rtas_addr);
> - if (ret < 0) {
> - fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
> - fdt_strerror(ret));
> - return ret;
> - }
> -
> - ret = qemu_fdt_setprop_cell(fdt, "/rtas", "linux,rtas-entry",
> - rtas_addr);
> - if (ret < 0) {
> - fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
> - fdt_strerror(ret));
> - return ret;
> - }
> -
> - ret = qemu_fdt_setprop_cell(fdt, "/rtas", "rtas-size",
> - rtas_size);
> - if (ret < 0) {
> - fprintf(stderr, "Couldn't add rtas-size property: %s\n",
> - fdt_strerror(ret));
> - return ret;
> - }
> -
> for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
> struct rtas_call *call = &rtas_table[i];
>
> @@ -751,6 +720,47 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
> return 0;
> }
>
> +void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr)
> +{
> + int rtas_node;
> + int ret;
> +
> + /* Copy RTAS blob into guest RAM */
> + cpu_physical_memory_write(addr, spapr->rtas_blob, spapr->rtas_size);
> +
> + ret = fdt_add_mem_rsv(fdt, addr, spapr->rtas_size);
> + if (ret < 0) {
> + fprintf(stderr, "Couldn't add RTAS reserve entry: %s\n",
> + fdt_strerror(ret));
> + exit(1);
> + }
> +
> + /* Update the device tree with the blob's location */
> + rtas_node = fdt_path_offset(fdt, "/rtas");
> + assert(rtas_node >= 0);
> +
> + ret = fdt_setprop_cell(fdt, rtas_node, "linux,rtas-base", addr);
> + if (ret < 0) {
> + fprintf(stderr, "Couldn't add linux,rtas-base property: %s\n",
> + fdt_strerror(ret));
> + exit(1);
> + }
> +
> + ret = fdt_setprop_cell(fdt, rtas_node, "linux,rtas-entry", addr);
> + if (ret < 0) {
> + fprintf(stderr, "Couldn't add linux,rtas-entry property: %s\n",
> + fdt_strerror(ret));
> + exit(1);
> + }
> +
> + ret = fdt_setprop_cell(fdt, rtas_node, "rtas-size", spapr->rtas_size);
> + if (ret < 0) {
> + fprintf(stderr, "Couldn't add rtas-size property: %s\n",
> + fdt_strerror(ret));
> + exit(1);
> + }
> +}
> +
> static void core_rtas_register_types(void)
> {
> spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index cd72586..ebad34f 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -512,6 +512,7 @@ target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *sm,
> uint32_t nret, target_ulong rets);
> int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
> hwaddr rtas_size);
> +void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr);
>
> #define SPAPR_TCE_PAGE_SHIFT 12
> #define SPAPR_TCE_PAGE_SIZE (1ULL << SPAPR_TCE_PAGE_SHIFT)
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 09/11] pseries: Consolidate construction of /chosen device tree node
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 09/11] pseries: Consolidate construction of /chosen device tree node David Gibson
@ 2016-04-21 5:32 ` Alexey Kardashevskiy
0 siblings, 0 replies; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:32 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> For historical reasons construction of the /chosen node in the device tree
> (amongst others) is split into several places. This patch brings these
> pieces back together to make things clearer.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> hw/ppc/spapr.c | 59 ++++++++++++++++++++--------------------------
> hw/ppc/spapr_vio.c | 16 +++----------
> include/hw/ppc/spapr_vio.h | 2 +-
> 3 files changed, 30 insertions(+), 47 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index d04d403..a000056 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -707,9 +707,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> MachineState *machine = MACHINE(spapr);
> sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
> const char *boot_device = machine->boot_order;
> - int ret, i;
> - size_t cb = 0;
> - char *bootlist;
> + int ret;
> void *fdt;
> sPAPRPHBState *phb;
> char *buf;
> @@ -759,6 +757,8 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> /* /chosen */
> {
> QDTNode *chosen = qdt_add_subnode(root, "chosen");
> + char *bootlist;
> + size_t cb = 0, i;
>
> /* Set Form1_affinity */
> qdt_setprop_bytes(chosen, "ibm,architecture-vec-5",
> @@ -782,6 +782,29 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> qdt_setprop_cells(chosen, "qemu,graphic-width", graphic_width);
> qdt_setprop_cells(chosen, "qemu,graphic-height", graphic_height);
> qdt_setprop_cells(chosen, "qemu,graphic-depth", graphic_depth);
> +
> + bootlist = get_boot_devices_list(&cb, true);
> + if (cb && bootlist) {
> + for (i = 0; i < cb; i++) {
> + if (bootlist[i] == '\n') {
> + bootlist[i] = ' ';
> + }
> +
> + }
> + qdt_setprop_string(chosen, "qemu,boot-list", bootlist);
> + }
> + g_free(bootlist);
> +
> + if (boot_device && strlen(boot_device)) {
> + qdt_setprop_string(chosen, "qemu,boot-device", boot_device);
> + }
> +
> + if (!spapr->has_graphics) {
> + char *stdout = spapr_vio_stdout_path(spapr->vio_bus);
> +
> + qdt_setprop_string(chosen, "linux,stdout-path", stdout);
> + g_free(stdout);
> + }
> }
>
> /* RTAS */
> @@ -933,40 +956,10 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> /* cpus */
> spapr_populate_cpus_dt_node(fdt, spapr);
>
> - bootlist = get_boot_devices_list(&cb, true);
> - if (cb && bootlist) {
> - int offset = fdt_path_offset(fdt, "/chosen");
> - if (offset < 0) {
> - exit(1);
> - }
> - for (i = 0; i < cb; i++) {
> - if (bootlist[i] == '\n') {
> - bootlist[i] = ' ';
> - }
> -
> - }
> - ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist);
> - }
> -
> - if (boot_device && strlen(boot_device)) {
> - int offset = fdt_path_offset(fdt, "/chosen");
> -
> - if (offset < 0) {
> - exit(1);
> - }
> - fdt_setprop_string(fdt, offset, "qemu,boot-device", boot_device);
> - }
> -
> - if (!spapr->has_graphics) {
> - spapr_populate_chosen_stdout(fdt, spapr->vio_bus);
> - }
> -
> if (smc->dr_lmb_enabled) {
> _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
> }
>
> - g_free(bootlist);
> -
> /* Build memory reserve map */
> if (spapr->kernel_size) {
> _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
> diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
> index 8aa021f..18b07e0 100644
> --- a/hw/ppc/spapr_vio.c
> +++ b/hw/ppc/spapr_vio.c
> @@ -679,28 +679,18 @@ out:
> return ret;
> }
>
> -int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus)
> +gchar *spapr_vio_stdout_path(VIOsPAPRBus *bus)
> {
> VIOsPAPRDevice *dev;
> char *name, *path;
> - int ret, offset;
>
> dev = spapr_vty_get_default(bus);
> if (!dev)
> - return 0;
> -
> - offset = fdt_path_offset(fdt, "/chosen");
> - if (offset < 0) {
> - return offset;
> - }
> + return NULL;
>
> name = spapr_vio_get_dev_name(DEVICE(dev));
> path = g_strdup_printf("/vdevice/%s", name);
> -
> - ret = fdt_setprop_string(fdt, offset, "linux,stdout-path", path);
> -
> g_free(name);
> - g_free(path);
>
> - return ret;
> + return path;
> }
> diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
> index c9733e7..ea00c3b 100644
> --- a/include/hw/ppc/spapr_vio.h
> +++ b/include/hw/ppc/spapr_vio.h
> @@ -82,7 +82,7 @@ struct VIOsPAPRBus {
> extern VIOsPAPRBus *spapr_vio_bus_init(void);
> extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
> extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
> -extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus);
> +gchar *spapr_vio_stdout_path(VIOsPAPRBus *bus);
>
> extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
>
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 10/11] pseries: Consolidate construction of /rtas device tree node
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 10/11] pseries: Consolidate construction of /rtas " David Gibson
@ 2016-04-21 5:32 ` Alexey Kardashevskiy
0 siblings, 0 replies; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 5:32 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> For historical reasons construction of the /rtas node in the device tree
> (amongst others) is split into several places. In particular it's split
> between spapr_build_fdt() and spapr_rtas_device_tree_setup().
>
> In fact, as well as adding the actual RTAS tokens to the device tree,
> spapr_rtas_device_tree_setup() just adds the ibm,lrdr-capacity property,
> which despite going in the /rtas node, doesn't have a lot to do with RTAS.
>
> This patch consolidates the code constructing /rtas together. Most of it
> goes inline (but together) into spapr_build_fdt(), and
> spapr_rtas_device_tree_setup() is renamed to spapr_rtas_dt_tokens() and
> now only adds the token properties.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> hw/ppc/spapr.c | 18 +++++++++++-------
> hw/ppc/spapr_rtas.c | 32 ++------------------------------
> include/hw/ppc/spapr.h | 4 ++--
> 3 files changed, 15 insertions(+), 39 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index a000056..f52add7 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -807,11 +807,13 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> }
> }
>
> - /* RTAS */
> + /* /rtas */
> {
> QDTNode *rtas = qdt_add_subnode(root, "rtas");
> GString *hypertas = g_string_sized_new(256);
> GString *qemu_hypertas = g_string_sized_new(256);
> + uint64_t max_hotplug_addr = spapr->hotplug_memory.base
> + + memory_region_size(&spapr->hotplug_memory.mr);
>
> add_str(hypertas, "hcall-pft");
> add_str(hypertas, "hcall-term");
> @@ -851,6 +853,14 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> * that rtas call return will always occur. Set this property.
> */
> qdt_setprop_empty(rtas, "ibm,extended-os-term");
> +
> + qdt_setprop_cells(rtas, "ibm,lrdr-capacity",
> + max_hotplug_addr >> 32,
> + max_hotplug_addr & 0xffffffff,
> + 0, SPAPR_MEMORY_BLOCK_SIZE,
> + max_cpus / smp_threads);
> +
> + spapr_rtas_dt_tokens(rtas);
> }
>
> /* /interrupt controller */
> @@ -947,12 +957,6 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> exit(1);
> }
>
> - /* RTAS */
> - ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size);
> - if (ret < 0) {
> - fprintf(stderr, "Couldn't set up RTAS device tree properties\n");
> - }
> -
> /* cpus */
> spapr_populate_cpus_dt_node(fdt, spapr);
>
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index c0cb41e..806a7b0 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -677,16 +677,9 @@ void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
> rtas_table[token].fn = fn;
> }
>
> -int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
> - hwaddr rtas_size)
> +void spapr_rtas_dt_tokens(QDTNode *node)
> {
> - int ret;
> int i;
> - uint32_t lrdr_capacity[5];
> - MachineState *machine = MACHINE(qdev_get_machine());
> - sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
> - uint64_t max_hotplug_addr = spapr->hotplug_memory.base +
> - memory_region_size(&spapr->hotplug_memory.mr);
>
> for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
> struct rtas_call *call = &rtas_table[i];
> @@ -695,29 +688,8 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
> continue;
> }
>
> - ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name,
> - i + RTAS_TOKEN_BASE);
> - if (ret < 0) {
> - fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
> - call->name, fdt_strerror(ret));
> - return ret;
> - }
> -
> + qdt_setprop_cells(node, call->name, i + RTAS_TOKEN_BASE);
> }
> -
> - lrdr_capacity[0] = cpu_to_be32(max_hotplug_addr >> 32);
> - lrdr_capacity[1] = cpu_to_be32(max_hotplug_addr & 0xffffffff);
> - lrdr_capacity[2] = 0;
> - lrdr_capacity[3] = cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE);
> - lrdr_capacity[4] = cpu_to_be32(max_cpus/smp_threads);
> - ret = qemu_fdt_setprop(fdt, "/rtas", "ibm,lrdr-capacity", lrdr_capacity,
> - sizeof(lrdr_capacity));
> - if (ret < 0) {
> - fprintf(stderr, "Couldn't add ibm,lrdr-capacity rtas property\n");
> - return ret;
> - }
> -
> - return 0;
> }
>
> void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr)
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 40d3724..1e609a0 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -6,6 +6,7 @@
> #include "hw/ppc/xics.h"
> #include "hw/ppc/spapr_drc.h"
> #include "hw/mem/pc-dimm.h"
> +#include "qemu/qdt.h"
>
> struct VIOsPAPRBus;
> struct sPAPRPHBState;
> @@ -510,8 +511,7 @@ void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn);
> target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *sm,
> uint32_t token, uint32_t nargs, target_ulong args,
> uint32_t nret, target_ulong rets);
> -int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
> - hwaddr rtas_size);
> +void spapr_rtas_dt_tokens(QDTNode *node);
> void spapr_load_rtas(sPAPRMachineState *spapr, void *fdt, hwaddr addr);
>
> #define SPAPR_TCE_PAGE_SHIFT 12
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries
2016-04-21 5:14 ` Alexey Kardashevskiy
@ 2016-04-21 5:52 ` David Gibson
2016-04-21 6:03 ` Alexey Kardashevskiy
0 siblings, 1 reply; 44+ messages in thread
From: David Gibson @ 2016-04-21 5:52 UTC (permalink / raw)
To: Alexey Kardashevskiy; +Cc: agraf, crosthwaite.peter, qemu-ppc, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 3065 bytes --]
On Thu, Apr 21, 2016 at 03:14:48PM +1000, Alexey Kardashevskiy wrote:
> On 04/20/2016 12:33 PM, David Gibson wrote:
> >The flattened device tree passed to pseries guests contains a list of
> >reserved memory areas. Currently we construct this list early in
> >spapr_build_fdt() as we sequentially write out the fdt.
> >
> >This will be inconvenient for upcoming cleanups, so this patch moves
> >the reserve map changes to the end of fdt construction. This changes
> >fdt_add_reservemap_entry() calls - which work when writing the fdt
> >sequentially to fdt_add_mem_rsv() calls used when altering the fdt in
> >random access mode.
>
>
> Looks to me like the real reason for this move is that new qdt_setprop_xxx
> API does not support memory reserve map yet. Will it, when?
Right, and it's not clear that it even should include reserve map
stuff. The reserve map isn't really part of the device tree, it's
just included in the fdt blob for historical and implementation
reasons.
So I'd prefer to avoid managing a list of reserve entries in qdt -
instead I was thinking of just having a list of reserves passed
straight into qdt_flatten().
In the meantime, I'd prefer to defer that design decision.
> In general, when
> do you plan to get rid of _FDT()?
Once I've got rid of all the calls to libfdt functions that need error
catching.
>
> Anyway,
>
> Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>
>
>
> >
> >Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> >---
> > hw/ppc/spapr.c | 17 +++++++++--------
> > 1 file changed, 9 insertions(+), 8 deletions(-)
> >
> >diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> >index 5356f4d..aef44a2 100644
> >--- a/hw/ppc/spapr.c
> >+++ b/hw/ppc/spapr.c
> >@@ -733,14 +733,6 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> > fdt = g_malloc0(FDT_MAX_SIZE);
> > _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
> >
> >- if (spapr->kernel_size) {
> >- _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
> >- spapr->kernel_size)));
> >- }
> >- if (spapr->initrd_size) {
> >- _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
> >- spapr->initrd_size)));
> >- }
> > _FDT((fdt_finish_reservemap(fdt)));
> >
> > /* Root node */
> >@@ -976,6 +968,15 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> > }
> >
> > g_free(bootlist);
> >+
> >+ /* Build memory reserve map */
> >+ if (spapr->kernel_size) {
> >+ _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
> >+ }
> >+ if (spapr->initrd_size) {
> >+ _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size)));
> >+ }
> >+
> > return fdt;
> > }
> >
> >
>
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code David Gibson
@ 2016-04-21 6:01 ` Alexey Kardashevskiy
2016-04-22 4:15 ` David Gibson
2016-04-26 11:00 ` Thomas Huth
1 sibling, 1 reply; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 6:01 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: qemu-ppc, qemu-devel
On 04/20/2016 12:33 PM, David Gibson wrote:
> A number of guests supported by qemu use IEEE12750 (Open Firmware)
> style device trees for hardware discovery. In some cases (mac99,
> pseries) they get this device tree via calls to an in-guest Open
> Firmware implementation, in others (many ppc and arm embedded
> machines) they consume the flattened ("fdt" or "dtb") format described
> in ePAPR amongst other places. In some cases this device tree is
> constructed in guest firmware, in others by qemu and in some cases
> it's a hybrid.
>
> The upshot is that a number of qemu machine types need to construct
> and/or manipulate device trees. Particularly with the pseries machine
> type, the complexity of manipulation it needs has been gradually
> increasing over time.
>
> For now, these machine types have generally worked with the device
> tree in the flattened format, using either libfdt directly or the
> wrappers in device_tree.c. However, the fdt format was designed
> primarily for transferring device trees between components, not for
> runtime manipulation:
> * fdt provides no persistent handles on nodes
> Nodes are referenced using offsets in the stream which can be
> altered by insertions or deletions elsewhere in the tree
> * libfdt operations can fail
> At any time the fdt lives in a limited size buffer, and
> operations can fail if it fills. This can be handled by
> resizing the buffer, but that means logic to catch this case
> on essentially every fdt operation, which is fiddly (in
> practice we usually just allocate a buffer with plenty of
> space and treat failures as fatal errors).
> * fdt manipulation is slow
> This probably isn't a problem in practice, but because it
> uses memmove() liberally, even trivial operations on an fdt
> are usually O(n) in the size of the whole tree. This can
> often make the obvious way of constructing the tree O(n^2) or
> worse. This could cause noticeable slow downs if someone
> builds a guest with hundreds or thousands of devices, which
> is an unusual but not unreasonable use case.
>
> This patch introduces a new utility library "qdt" for runtime
> manipulation of device trees. The intention is that machine type code
> can use these routines to construct the device tree conveniently,
> using a pointer-based representation doesn't have the limitations
> above. They can then use qdt_flatten() to convert the completed tree
> to fdt format as a single O(n) operation to pass to the guest.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
With few comments,
Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> include/qemu/qdt.h | 102 +++++++++++++++++++++
> util/Makefile.objs | 1 +
> util/qdt.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 365 insertions(+)
> create mode 100644 include/qemu/qdt.h
> create mode 100644 util/qdt.c
>
> diff --git a/include/qemu/qdt.h b/include/qemu/qdt.h
> new file mode 100644
> index 0000000..bff7143
> --- /dev/null
> +++ b/include/qemu/qdt.h
> @@ -0,0 +1,102 @@
> +/*
> + * Functions for manipulating IEEE1275 (Open Firmware) style device
> + * trees.
> + *
> + * Copyright David Gibson, Red Hat Inc. 2016
> + *
> + * This work is licensed unter the GNU GPL version 2 or (at your
> + * option) any later version.
> + */
> +#ifndef QEMU_QDT_H__
> +#define QEMU_QDT_H__
> +
> +#include <string.h>
> +#include <stdint.h>
> +#include <glib.h>
> +#include "qemu/queue.h"
> +
> +typedef struct QDTProperty QDTProperty;
> +typedef struct QDTNode QDTNode;
> +
> +struct QDTProperty {
> + gchar *name;
> + QTAILQ_ENTRY(QDTProperty) list;
> + gsize len;
> + uint8_t val[];
> +};
> +
> +struct QDTNode {
> + gchar *name;
> + QDTNode *parent;
> + QTAILQ_HEAD(, QDTProperty) properties;
> + QTAILQ_HEAD(, QDTNode) children;
> + QTAILQ_ENTRY(QDTNode) sibling;
> +};
> +
> +/*
> + * Node functions
> + */
> +
> +QDTNode *qdt_new_node(const gchar *name);
> +QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path);
> +QDTNode *qdt_get_node(QDTNode *root, const gchar *path);
Do you really need both qdt_get_node_relative and qdt_get_node? It would
make sense (a little) if qdt_get_node() accepted path without leading "/"
but it does not.
> +QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name);
> +
> +static inline QDTNode *qdt_new_tree(void)
> +{
> + return qdt_new_node("");
> +}
> +
> +/*
> + * Property functions
> + */
> +
> +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len);
> +const QDTProperty *qdt_getprop(const QDTNode *node, const gchar *name);
> +void qdt_delprop(QDTNode *node, const gchar *name);
> +const QDTProperty *qdt_setprop(QDTNode *node, const gchar *name,
> + gconstpointer val, gsize len);
> +const QDTProperty *qdt_setprop_cells_(QDTNode *node, const gchar *name,
> + const uint32_t *val, gsize len);
> +const QDTProperty *qdt_setprop_u64s_(QDTNode *node, const char *name,
s/char/gchar/ ?
> + const uint64_t *val, gsize len);
> +const QDTProperty *qdt_setprop_string(QDTNode *node, const gchar *name,
> + const gchar *val);
> +void qdt_set_phandle(QDTNode *node, uint32_t phandle);
> +
> +#define qdt_setprop_bytes(node, name, ...) \
> + ({ \
> + uint8_t vals[] = { __VA_ARGS__ }; \
> + qdt_setprop((node), (name), vals, sizeof(vals)); \
> + })
> +#define qdt_setprop_cells(node, name, ...) \
> + ({ \
> + uint32_t vals[] = { __VA_ARGS__ }; \
> + qdt_setprop_cells_((node), (name), \
> + vals, sizeof(vals) / sizeof(vals[0])); \
Nit: there is ARRAY_SIZE(x).
> + })
> +#define qdt_setprop_u64s(node, name, ...) \
> + ({ \
> + uint64_t vals[] = { __VA_ARGS__ }; \
> + qdt_setprop_u64s_((node), (name), \
> + vals, sizeof(vals) / sizeof(vals[0])); \
> + })
> +static inline const QDTProperty *qdt_setprop_empty(QDTNode *node,
> + const gchar *name)
> +{
> + return qdt_setprop_bytes(node, name);
> +}
> +static inline const QDTProperty *qdt_setprop_dup(QDTNode *node,
> + const gchar *name,
> + const QDTProperty *oldprop)
Out of curiosity - when could I possibly want to use this?
> +{
> + return qdt_setprop(node, name, oldprop->val, oldprop->len);
> +}
> +
> +/*
> + * Whole tree functions
> + */
> +
> +void *qdt_flatten(QDTNode *root, gsize bufsize, Error **errp);
> +
> +#endif /* QEMU_QDT_H__ */
> diff --git a/util/Makefile.objs b/util/Makefile.objs
> index a8a777e..f1d639f 100644
> --- a/util/Makefile.objs
> +++ b/util/Makefile.objs
> @@ -32,3 +32,4 @@ util-obj-y += buffer.o
> util-obj-y += timed-average.o
> util-obj-y += base64.o
> util-obj-y += log.o
> +util-obj-y += qdt.o
> diff --git a/util/qdt.c b/util/qdt.c
> new file mode 100644
> index 0000000..e3a449a
> --- /dev/null
> +++ b/util/qdt.c
> @@ -0,0 +1,262 @@
> +/*
> + * Functions for manipulating IEEE1275 (Open Firmware) style device
> + * trees.
> + *
> + * Copyright David Gibson, Red Hat Inc. 2016
> + *
> + * This work is licensed unter the GNU GPL version 2 or (at your
> + * option) any later version.
> + */
> +
> +#include <libfdt.h>
> +#include <stdbool.h>
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/qdt.h"
> +#include "qemu/error-report.h"
> +
> +/*
> + * Node functions
> + */
> +
> +QDTNode *qdt_new_node(const gchar *name)
> +{
> + QDTNode *node = g_new0(QDTNode, 1);
> +
> + g_assert(!strchr(name, '/'));
> +
> + node->name = g_strdup(name);
> + QTAILQ_INIT(&node->properties);
> + QTAILQ_INIT(&node->children);
> +
> + return node;
> +}
> +
> +static QDTNode *get_subnode(QDTNode *parent, const gchar *name, size_t namelen)
> +{
> + QDTNode *child;
> +
> + g_assert(!memchr(name, '/', namelen));
> +
> + QTAILQ_FOREACH(child, &parent->children, sibling) {
> + if ((strlen(child->name) == namelen)
> + && (memcmp(child->name, name, namelen) == 0)) {
> + return child;
> + }
> + }
> +
> + return NULL;
> +}
> +
> +QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path)
> +{
> + const gchar *slash;
> + gsize seglen;
> +
> + do {
> + slash = strchr(path, '/');
> + seglen = slash ? slash - path : strlen(path);
> +
> + node = get_subnode(node, path, seglen);
> + path += seglen + 1;
> + } while (node && slash);
> +
> + return node;
> +}
> +
> +QDTNode *qdt_get_node(QDTNode *root, const gchar *path)
> +{
> + g_assert(!root->parent);
> + g_assert(path[0] == '/');
> + return qdt_get_node_relative(root, path + 1);
> +}
> +
> +QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name)
> +{
> + QDTNode *new = qdt_new_node(name);
> +
> + new->parent = parent;
> + QTAILQ_INSERT_TAIL(&parent->children, new, sibling);
> + return new;
> +}
> +
> +/*
> + * Property functions
> + */
> +
> +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
> +{
> + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
> +
> + prop->name = g_strdup(name);
> + prop->len = len;
> + memcpy(prop->val, val, len);
> + return prop;
> +}
> +
> +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
> +{
> + QDTProperty *prop;
> +
> + QTAILQ_FOREACH(prop, &node->properties, list) {
> + if (strcmp(prop->name, name) == 0) {
> + return prop;
> + }
> + }
> + return NULL;
> +}
> +
> +const QDTProperty *qdt_getprop(const QDTNode *node, const gchar *name)
> +{
> + return getprop_(node, name);
> +}
> +
> +void qdt_delprop(QDTNode *node, const gchar *name)
> +{
> + QDTProperty *prop = getprop_(node, name);
> +
> + if (prop) {
> + QTAILQ_REMOVE(&node->properties, prop, list);
> + g_free(prop->name);
> + g_free(prop);
> + }
> +}
> +
> +const QDTProperty *qdt_setprop(QDTNode *node, const gchar *name,
> + gconstpointer val, gsize len)
> +{
> + QDTProperty *prop;
> +
> + qdt_delprop(node, name);
> +
> + prop = g_malloc0(sizeof(*prop) + len);
> + prop->name = g_strdup(name);
> + prop->len = len;
> + memcpy(prop->val, val, len);
> + QTAILQ_INSERT_TAIL(&node->properties, prop, list);
> + return prop;
> +}
> +
> +const QDTProperty *qdt_setprop_string(QDTNode *node, const gchar *name,
> + const gchar *val)
> +{
> + return qdt_setprop(node, name, val, strlen(val) + 1);
> +}
> +
> +const QDTProperty *qdt_setprop_cells_(QDTNode *node, const gchar *name,
> + const uint32_t *val, gsize len)
> +{
> + uint32_t swapval[len];
> + gsize i;
> +
> + for (i = 0; i < len; i++) {
> + swapval[i] = cpu_to_fdt32(val[i]);
> + }
> + return qdt_setprop(node, name, swapval, sizeof(swapval));
> +}
> +
> +const QDTProperty *qdt_setprop_u64s_(QDTNode *node, const char *name,
> + const uint64_t *val, gsize len)
> +{
> + uint64_t swapval[len];
> + gsize i;
> +
> + for (i = 0; i < len; i++) {
> + swapval[i] = cpu_to_fdt64(val[i]);
> + }
> + return qdt_setprop(node, name, swapval, sizeof(swapval));
> +}
> +
> +void qdt_set_phandle(QDTNode *node, uint32_t phandle)
> +{
> + g_assert((phandle != 0) && (phandle != (uint32_t)-1));
> + qdt_setprop_cells(node, "linux,phandle", phandle);
> + qdt_setprop_cells(node, "phandle", phandle);
> +}
> +
> +/*
> + * Whole tree functions
> + */
> +
> +static void qdt_flatten_node(void *fdt, QDTNode *node, Error **errp)
> +{
> + QDTProperty *prop;
> + QDTNode *subnode;
> + Error *local_err = NULL;
> + int ret;
> +
> + ret = fdt_begin_node(fdt, node->name);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_begin_node(): %s",
> + fdt_strerror(ret));
> + return;
> + }
> +
> + QTAILQ_FOREACH(prop, &node->properties, list) {
> + ret = fdt_property(fdt, prop->name, prop->val, prop->len);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_property(): %s",
> + fdt_strerror(ret));
> + return;
> + }
> + }
> +
> + QTAILQ_FOREACH(subnode, &node->children, sibling) {
> + qdt_flatten_node(fdt, subnode, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + }
> +
> + ret = fdt_end_node(fdt);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_end_node(): %s",
> + fdt_strerror(ret));
> + return;
> + }
> +}
> +
> +void *qdt_flatten(QDTNode *root, gsize bufsize, Error **errp)
> +{
> + void *fdt = g_malloc0(bufsize);
> + Error *local_err = NULL;
> + int ret;
> +
> + assert(!root->parent); /* Should be a root node */
> +
> + ret = fdt_create(fdt, bufsize);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_create(): %s",
> + fdt_strerror(ret));
> + goto fail;
> + }
> +
> + ret = fdt_finish_reservemap(fdt);
> + if (ret < 0) {
> + error_setg(errp,
> + "Error flattening device tree: fdt_finish_reservemap(): %s",
> + fdt_strerror(ret));
> + goto fail;
> + }
> +
> + qdt_flatten_node(fdt, root, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + goto fail;
> + }
> +
> + ret = fdt_finish(fdt);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_finish(): %s",
> + fdt_strerror(ret));
> + goto fail;
> + }
> +
> + return fdt;
> +
> +fail:
> + g_free(fdt);
> + return NULL;
> +}
>
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries
2016-04-21 5:52 ` David Gibson
@ 2016-04-21 6:03 ` Alexey Kardashevskiy
2016-04-22 4:22 ` David Gibson
0 siblings, 1 reply; 44+ messages in thread
From: Alexey Kardashevskiy @ 2016-04-21 6:03 UTC (permalink / raw)
To: David Gibson; +Cc: qemu-devel, qemu-ppc, agraf, crosthwaite.peter
On 04/21/2016 03:52 PM, David Gibson wrote:
> On Thu, Apr 21, 2016 at 03:14:48PM +1000, Alexey Kardashevskiy wrote:
>> On 04/20/2016 12:33 PM, David Gibson wrote:
>>> The flattened device tree passed to pseries guests contains a list of
>>> reserved memory areas. Currently we construct this list early in
>>> spapr_build_fdt() as we sequentially write out the fdt.
>>>
>>> This will be inconvenient for upcoming cleanups, so this patch moves
>>> the reserve map changes to the end of fdt construction. This changes
>>> fdt_add_reservemap_entry() calls - which work when writing the fdt
>>> sequentially to fdt_add_mem_rsv() calls used when altering the fdt in
>>> random access mode.
>>
>>
>> Looks to me like the real reason for this move is that new qdt_setprop_xxx
>> API does not support memory reserve map yet. Will it, when?
>
> Right, and it's not clear that it even should include reserve map
> stuff. The reserve map isn't really part of the device tree, it's
> just included in the fdt blob for historical and implementation
> reasons.
>
> So I'd prefer to avoid managing a list of reserve entries in qdt -
> instead I was thinking of just having a list of reserves passed
> straight into qdt_flatten().
>
> In the meantime, I'd prefer to defer that design decision.
Ok.
>> In general, when
>> do you plan to get rid of _FDT()?
>
> Once I've got rid of all the calls to libfdt functions that need error
> catching.
I meant timeframe :) Like "2.7 release" or so.
--
Alexey
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-21 6:01 ` Alexey Kardashevskiy
@ 2016-04-22 4:15 ` David Gibson
0 siblings, 0 replies; 44+ messages in thread
From: David Gibson @ 2016-04-22 4:15 UTC (permalink / raw)
To: Alexey Kardashevskiy; +Cc: agraf, crosthwaite.peter, qemu-ppc, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 16283 bytes --]
On Thu, Apr 21, 2016 at 04:01:16PM +1000, Alexey Kardashevskiy wrote:
> On 04/20/2016 12:33 PM, David Gibson wrote:
> >A number of guests supported by qemu use IEEE12750 (Open Firmware)
> >style device trees for hardware discovery. In some cases (mac99,
> >pseries) they get this device tree via calls to an in-guest Open
> >Firmware implementation, in others (many ppc and arm embedded
> >machines) they consume the flattened ("fdt" or "dtb") format described
> >in ePAPR amongst other places. In some cases this device tree is
> >constructed in guest firmware, in others by qemu and in some cases
> >it's a hybrid.
> >
> >The upshot is that a number of qemu machine types need to construct
> >and/or manipulate device trees. Particularly with the pseries machine
> >type, the complexity of manipulation it needs has been gradually
> >increasing over time.
> >
> >For now, these machine types have generally worked with the device
> >tree in the flattened format, using either libfdt directly or the
> >wrappers in device_tree.c. However, the fdt format was designed
> >primarily for transferring device trees between components, not for
> >runtime manipulation:
> > * fdt provides no persistent handles on nodes
> > Nodes are referenced using offsets in the stream which can be
> > altered by insertions or deletions elsewhere in the tree
> > * libfdt operations can fail
> > At any time the fdt lives in a limited size buffer, and
> > operations can fail if it fills. This can be handled by
> > resizing the buffer, but that means logic to catch this case
> > on essentially every fdt operation, which is fiddly (in
> > practice we usually just allocate a buffer with plenty of
> > space and treat failures as fatal errors).
> > * fdt manipulation is slow
> > This probably isn't a problem in practice, but because it
> > uses memmove() liberally, even trivial operations on an fdt
> > are usually O(n) in the size of the whole tree. This can
> > often make the obvious way of constructing the tree O(n^2) or
> > worse. This could cause noticeable slow downs if someone
> > builds a guest with hundreds or thousands of devices, which
> > is an unusual but not unreasonable use case.
> >
> >This patch introduces a new utility library "qdt" for runtime
> >manipulation of device trees. The intention is that machine type code
> >can use these routines to construct the device tree conveniently,
> >using a pointer-based representation doesn't have the limitations
> >above. They can then use qdt_flatten() to convert the completed tree
> >to fdt format as a single O(n) operation to pass to the guest.
> >
> >Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>
>
> With few comments,
>
>
> Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>
>
>
>
> >---
> > include/qemu/qdt.h | 102 +++++++++++++++++++++
> > util/Makefile.objs | 1 +
> > util/qdt.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 365 insertions(+)
> > create mode 100644 include/qemu/qdt.h
> > create mode 100644 util/qdt.c
> >
> >diff --git a/include/qemu/qdt.h b/include/qemu/qdt.h
> >new file mode 100644
> >index 0000000..bff7143
> >--- /dev/null
> >+++ b/include/qemu/qdt.h
> >@@ -0,0 +1,102 @@
> >+/*
> >+ * Functions for manipulating IEEE1275 (Open Firmware) style device
> >+ * trees.
> >+ *
> >+ * Copyright David Gibson, Red Hat Inc. 2016
> >+ *
> >+ * This work is licensed unter the GNU GPL version 2 or (at your
> >+ * option) any later version.
> >+ */
> >+#ifndef QEMU_QDT_H__
> >+#define QEMU_QDT_H__
> >+
> >+#include <string.h>
> >+#include <stdint.h>
> >+#include <glib.h>
> >+#include "qemu/queue.h"
> >+
> >+typedef struct QDTProperty QDTProperty;
> >+typedef struct QDTNode QDTNode;
> >+
> >+struct QDTProperty {
> >+ gchar *name;
> >+ QTAILQ_ENTRY(QDTProperty) list;
> >+ gsize len;
> >+ uint8_t val[];
> >+};
> >+
> >+struct QDTNode {
> >+ gchar *name;
> >+ QDTNode *parent;
> >+ QTAILQ_HEAD(, QDTProperty) properties;
> >+ QTAILQ_HEAD(, QDTNode) children;
> >+ QTAILQ_ENTRY(QDTNode) sibling;
> >+};
> >+
> >+/*
> >+ * Node functions
> >+ */
> >+
> >+QDTNode *qdt_new_node(const gchar *name);
> >+QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path);
> >+QDTNode *qdt_get_node(QDTNode *root, const gchar *path);
>
>
> Do you really need both qdt_get_node_relative and qdt_get_node? It would
> make sense (a little) if qdt_get_node() accepted path without leading "/"
> but it does not.
Hm, maybe not. I'll see if I can combine those.
>
>
> >+QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name);
> >+
> >+static inline QDTNode *qdt_new_tree(void)
> >+{
> >+ return qdt_new_node("");
> >+}
> >+
> >+/*
> >+ * Property functions
> >+ */
> >+
> >+QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len);
> >+const QDTProperty *qdt_getprop(const QDTNode *node, const gchar *name);
> >+void qdt_delprop(QDTNode *node, const gchar *name);
> >+const QDTProperty *qdt_setprop(QDTNode *node, const gchar *name,
> >+ gconstpointer val, gsize len);
> >+const QDTProperty *qdt_setprop_cells_(QDTNode *node, const gchar *name,
> >+ const uint32_t *val, gsize len);
> >+const QDTProperty *qdt_setprop_u64s_(QDTNode *node, const char *name,
>
>
> s/char/gchar/ ?
Will change, thanks.
> >+ const uint64_t *val, gsize len);
> >+const QDTProperty *qdt_setprop_string(QDTNode *node, const gchar *name,
> >+ const gchar *val);
> >+void qdt_set_phandle(QDTNode *node, uint32_t phandle);
> >+
> >+#define qdt_setprop_bytes(node, name, ...) \
> >+ ({ \
> >+ uint8_t vals[] = { __VA_ARGS__ }; \
> >+ qdt_setprop((node), (name), vals, sizeof(vals)); \
> >+ })
> >+#define qdt_setprop_cells(node, name, ...) \
> >+ ({ \
> >+ uint32_t vals[] = { __VA_ARGS__ }; \
> >+ qdt_setprop_cells_((node), (name), \
> >+ vals, sizeof(vals) / sizeof(vals[0])); \
>
>
> Nit: there is ARRAY_SIZE(x).
Oh, yes. For some reason I thought I'd looked and not seen it there,
but I was obviously confused. Will change
> >+ })
> >+#define qdt_setprop_u64s(node, name, ...) \
> >+ ({ \
> >+ uint64_t vals[] = { __VA_ARGS__ }; \
> >+ qdt_setprop_u64s_((node), (name), \
> >+ vals, sizeof(vals) / sizeof(vals[0])); \
> >+ })
> >+static inline const QDTProperty *qdt_setprop_empty(QDTNode *node,
> >+ const gchar *name)
> >+{
> >+ return qdt_setprop_bytes(node, name);
> >+}
> >+static inline const QDTProperty *qdt_setprop_dup(QDTNode *node,
> >+ const gchar *name,
> >+ const QDTProperty *oldprop)
>
> Out of curiosity - when could I possibly want to use this?
Uh.. I thought I had a use case in the papr stuff I was already using,
but then I couldn't find it. I'll think about removing this.
> >+{
> >+ return qdt_setprop(node, name, oldprop->val, oldprop->len);
> >+}
> >+
> >+/*
> >+ * Whole tree functions
> >+ */
> >+
> >+void *qdt_flatten(QDTNode *root, gsize bufsize, Error **errp);
> >+
> >+#endif /* QEMU_QDT_H__ */
> >diff --git a/util/Makefile.objs b/util/Makefile.objs
> >index a8a777e..f1d639f 100644
> >--- a/util/Makefile.objs
> >+++ b/util/Makefile.objs
> >@@ -32,3 +32,4 @@ util-obj-y += buffer.o
> > util-obj-y += timed-average.o
> > util-obj-y += base64.o
> > util-obj-y += log.o
> >+util-obj-y += qdt.o
> >diff --git a/util/qdt.c b/util/qdt.c
> >new file mode 100644
> >index 0000000..e3a449a
> >--- /dev/null
> >+++ b/util/qdt.c
> >@@ -0,0 +1,262 @@
> >+/*
> >+ * Functions for manipulating IEEE1275 (Open Firmware) style device
> >+ * trees.
> >+ *
> >+ * Copyright David Gibson, Red Hat Inc. 2016
> >+ *
> >+ * This work is licensed unter the GNU GPL version 2 or (at your
> >+ * option) any later version.
> >+ */
> >+
> >+#include <libfdt.h>
> >+#include <stdbool.h>
> >+
> >+#include "qemu/osdep.h"
> >+#include "qapi/error.h"
> >+#include "qemu/qdt.h"
> >+#include "qemu/error-report.h"
> >+
> >+/*
> >+ * Node functions
> >+ */
> >+
> >+QDTNode *qdt_new_node(const gchar *name)
> >+{
> >+ QDTNode *node = g_new0(QDTNode, 1);
> >+
> >+ g_assert(!strchr(name, '/'));
> >+
> >+ node->name = g_strdup(name);
> >+ QTAILQ_INIT(&node->properties);
> >+ QTAILQ_INIT(&node->children);
> >+
> >+ return node;
> >+}
> >+
> >+static QDTNode *get_subnode(QDTNode *parent, const gchar *name, size_t namelen)
> >+{
> >+ QDTNode *child;
> >+
> >+ g_assert(!memchr(name, '/', namelen));
> >+
> >+ QTAILQ_FOREACH(child, &parent->children, sibling) {
> >+ if ((strlen(child->name) == namelen)
> >+ && (memcmp(child->name, name, namelen) == 0)) {
> >+ return child;
> >+ }
> >+ }
> >+
> >+ return NULL;
> >+}
> >+
> >+QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path)
> >+{
> >+ const gchar *slash;
> >+ gsize seglen;
> >+
> >+ do {
> >+ slash = strchr(path, '/');
> >+ seglen = slash ? slash - path : strlen(path);
> >+
> >+ node = get_subnode(node, path, seglen);
> >+ path += seglen + 1;
> >+ } while (node && slash);
> >+
> >+ return node;
> >+}
> >+
> >+QDTNode *qdt_get_node(QDTNode *root, const gchar *path)
> >+{
> >+ g_assert(!root->parent);
> >+ g_assert(path[0] == '/');
> >+ return qdt_get_node_relative(root, path + 1);
> >+}
> >+
> >+QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name)
> >+{
> >+ QDTNode *new = qdt_new_node(name);
> >+
> >+ new->parent = parent;
> >+ QTAILQ_INSERT_TAIL(&parent->children, new, sibling);
> >+ return new;
> >+}
> >+
> >+/*
> >+ * Property functions
> >+ */
> >+
> >+QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
> >+{
> >+ QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
> >+
> >+ prop->name = g_strdup(name);
> >+ prop->len = len;
> >+ memcpy(prop->val, val, len);
> >+ return prop;
> >+}
> >+
> >+static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
> >+{
> >+ QDTProperty *prop;
> >+
> >+ QTAILQ_FOREACH(prop, &node->properties, list) {
> >+ if (strcmp(prop->name, name) == 0) {
> >+ return prop;
> >+ }
> >+ }
> >+ return NULL;
> >+}
> >+
> >+const QDTProperty *qdt_getprop(const QDTNode *node, const gchar *name)
> >+{
> >+ return getprop_(node, name);
> >+}
> >+
> >+void qdt_delprop(QDTNode *node, const gchar *name)
> >+{
> >+ QDTProperty *prop = getprop_(node, name);
> >+
> >+ if (prop) {
> >+ QTAILQ_REMOVE(&node->properties, prop, list);
> >+ g_free(prop->name);
> >+ g_free(prop);
> >+ }
> >+}
> >+
> >+const QDTProperty *qdt_setprop(QDTNode *node, const gchar *name,
> >+ gconstpointer val, gsize len)
> >+{
> >+ QDTProperty *prop;
> >+
> >+ qdt_delprop(node, name);
> >+
> >+ prop = g_malloc0(sizeof(*prop) + len);
> >+ prop->name = g_strdup(name);
> >+ prop->len = len;
> >+ memcpy(prop->val, val, len);
> >+ QTAILQ_INSERT_TAIL(&node->properties, prop, list);
> >+ return prop;
> >+}
> >+
> >+const QDTProperty *qdt_setprop_string(QDTNode *node, const gchar *name,
> >+ const gchar *val)
> >+{
> >+ return qdt_setprop(node, name, val, strlen(val) + 1);
> >+}
> >+
> >+const QDTProperty *qdt_setprop_cells_(QDTNode *node, const gchar *name,
> >+ const uint32_t *val, gsize len)
> >+{
> >+ uint32_t swapval[len];
> >+ gsize i;
> >+
> >+ for (i = 0; i < len; i++) {
> >+ swapval[i] = cpu_to_fdt32(val[i]);
> >+ }
> >+ return qdt_setprop(node, name, swapval, sizeof(swapval));
> >+}
> >+
> >+const QDTProperty *qdt_setprop_u64s_(QDTNode *node, const char *name,
> >+ const uint64_t *val, gsize len)
> >+{
> >+ uint64_t swapval[len];
> >+ gsize i;
> >+
> >+ for (i = 0; i < len; i++) {
> >+ swapval[i] = cpu_to_fdt64(val[i]);
> >+ }
> >+ return qdt_setprop(node, name, swapval, sizeof(swapval));
> >+}
> >+
> >+void qdt_set_phandle(QDTNode *node, uint32_t phandle)
> >+{
> >+ g_assert((phandle != 0) && (phandle != (uint32_t)-1));
> >+ qdt_setprop_cells(node, "linux,phandle", phandle);
> >+ qdt_setprop_cells(node, "phandle", phandle);
> >+}
> >+
> >+/*
> >+ * Whole tree functions
> >+ */
> >+
> >+static void qdt_flatten_node(void *fdt, QDTNode *node, Error **errp)
> >+{
> >+ QDTProperty *prop;
> >+ QDTNode *subnode;
> >+ Error *local_err = NULL;
> >+ int ret;
> >+
> >+ ret = fdt_begin_node(fdt, node->name);
> >+ if (ret < 0) {
> >+ error_setg(errp, "Error flattening device tree: fdt_begin_node(): %s",
> >+ fdt_strerror(ret));
> >+ return;
> >+ }
> >+
> >+ QTAILQ_FOREACH(prop, &node->properties, list) {
> >+ ret = fdt_property(fdt, prop->name, prop->val, prop->len);
> >+ if (ret < 0) {
> >+ error_setg(errp, "Error flattening device tree: fdt_property(): %s",
> >+ fdt_strerror(ret));
> >+ return;
> >+ }
> >+ }
> >+
> >+ QTAILQ_FOREACH(subnode, &node->children, sibling) {
> >+ qdt_flatten_node(fdt, subnode, &local_err);
> >+ if (local_err) {
> >+ error_propagate(errp, local_err);
> >+ return;
> >+ }
> >+ }
> >+
> >+ ret = fdt_end_node(fdt);
> >+ if (ret < 0) {
> >+ error_setg(errp, "Error flattening device tree: fdt_end_node(): %s",
> >+ fdt_strerror(ret));
> >+ return;
> >+ }
> >+}
> >+
> >+void *qdt_flatten(QDTNode *root, gsize bufsize, Error **errp)
> >+{
> >+ void *fdt = g_malloc0(bufsize);
> >+ Error *local_err = NULL;
> >+ int ret;
> >+
> >+ assert(!root->parent); /* Should be a root node */
> >+
> >+ ret = fdt_create(fdt, bufsize);
> >+ if (ret < 0) {
> >+ error_setg(errp, "Error flattening device tree: fdt_create(): %s",
> >+ fdt_strerror(ret));
> >+ goto fail;
> >+ }
> >+
> >+ ret = fdt_finish_reservemap(fdt);
> >+ if (ret < 0) {
> >+ error_setg(errp,
> >+ "Error flattening device tree: fdt_finish_reservemap(): %s",
> >+ fdt_strerror(ret));
> >+ goto fail;
> >+ }
> >+
> >+ qdt_flatten_node(fdt, root, &local_err);
> >+ if (local_err) {
> >+ error_propagate(errp, local_err);
> >+ goto fail;
> >+ }
> >+
> >+ ret = fdt_finish(fdt);
> >+ if (ret < 0) {
> >+ error_setg(errp, "Error flattening device tree: fdt_finish(): %s",
> >+ fdt_strerror(ret));
> >+ goto fail;
> >+ }
> >+
> >+ return fdt;
> >+
> >+fail:
> >+ g_free(fdt);
> >+ return NULL;
> >+}
> >
>
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries
2016-04-21 6:03 ` Alexey Kardashevskiy
@ 2016-04-22 4:22 ` David Gibson
0 siblings, 0 replies; 44+ messages in thread
From: David Gibson @ 2016-04-22 4:22 UTC (permalink / raw)
To: Alexey Kardashevskiy; +Cc: qemu-devel, qemu-ppc, agraf, crosthwaite.peter
[-- Attachment #1: Type: text/plain, Size: 1965 bytes --]
On Thu, Apr 21, 2016 at 04:03:12PM +1000, Alexey Kardashevskiy wrote:
> On 04/21/2016 03:52 PM, David Gibson wrote:
> >On Thu, Apr 21, 2016 at 03:14:48PM +1000, Alexey Kardashevskiy wrote:
> >>On 04/20/2016 12:33 PM, David Gibson wrote:
> >>>The flattened device tree passed to pseries guests contains a list of
> >>>reserved memory areas. Currently we construct this list early in
> >>>spapr_build_fdt() as we sequentially write out the fdt.
> >>>
> >>>This will be inconvenient for upcoming cleanups, so this patch moves
> >>>the reserve map changes to the end of fdt construction. This changes
> >>>fdt_add_reservemap_entry() calls - which work when writing the fdt
> >>>sequentially to fdt_add_mem_rsv() calls used when altering the fdt in
> >>>random access mode.
> >>
> >>
> >>Looks to me like the real reason for this move is that new qdt_setprop_xxx
> >>API does not support memory reserve map yet. Will it, when?
> >
> >Right, and it's not clear that it even should include reserve map
> >stuff. The reserve map isn't really part of the device tree, it's
> >just included in the fdt blob for historical and implementation
> >reasons.
> >
> >So I'd prefer to avoid managing a list of reserve entries in qdt -
> >instead I was thinking of just having a list of reserves passed
> >straight into qdt_flatten().
> >
> >In the meantime, I'd prefer to defer that design decision.
>
>
> Ok.
>
> >>In general, when
> >>do you plan to get rid of _FDT()?
> >
> >Once I've got rid of all the calls to libfdt functions that need error
> >catching.
>
> I meant timeframe :) Like "2.7 release" or so.
Well.. it'd be nice to do this before the 2.7 release, but it really
depends how much time I have to do this cleanup stuff.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code David Gibson
2016-04-21 6:01 ` Alexey Kardashevskiy
@ 2016-04-26 11:00 ` Thomas Huth
2016-04-27 6:02 ` David Gibson
1 sibling, 1 reply; 44+ messages in thread
From: Thomas Huth @ 2016-04-26 11:00 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel
On 20.04.2016 04:33, David Gibson wrote:
...
> This patch introduces a new utility library "qdt" for runtime
> manipulation of device trees. The intention is that machine type code
> can use these routines to construct the device tree conveniently,
> using a pointer-based representation doesn't have the limitations
> above. They can then use qdt_flatten() to convert the completed tree
> to fdt format as a single O(n) operation to pass to the guest.
Good idea, the FDT format itself is really not very well suited for
dynamic manipulations...
...
> diff --git a/util/qdt.c b/util/qdt.c
> new file mode 100644
> index 0000000..e3a449a
> --- /dev/null
> +++ b/util/qdt.c
> @@ -0,0 +1,262 @@
> +/*
> + * Functions for manipulating IEEE1275 (Open Firmware) style device
> + * trees.
What does QDT stand for? Maybe add that in the description here.
> + * Copyright David Gibson, Red Hat Inc. 2016
> + *
> + * This work is licensed unter the GNU GPL version 2 or (at your
> + * option) any later version.
> + */
> +
> +#include <libfdt.h>
> +#include <stdbool.h>
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/qdt.h"
> +#include "qemu/error-report.h"
> +
> +/*
> + * Node functions
> + */
> +
> +QDTNode *qdt_new_node(const gchar *name)
> +{
> + QDTNode *node = g_new0(QDTNode, 1);
> +
> + g_assert(!strchr(name, '/'));
> +
> + node->name = g_strdup(name);
> + QTAILQ_INIT(&node->properties);
> + QTAILQ_INIT(&node->children);
> +
> + return node;
> +}
> +
> +static QDTNode *get_subnode(QDTNode *parent, const gchar *name, size_t namelen)
> +{
> + QDTNode *child;
> +
> + g_assert(!memchr(name, '/', namelen));
> +
> + QTAILQ_FOREACH(child, &parent->children, sibling) {
> + if ((strlen(child->name) == namelen)
> + && (memcmp(child->name, name, namelen) == 0)) {
Too many parenthesis for my taste ;-)
> + return child;
> + }
> + }
> +
> + return NULL;
> +}
> +
> +QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path)
> +{
> + const gchar *slash;
> + gsize seglen;
> +
> + do {
> + slash = strchr(path, '/');
> + seglen = slash ? slash - path : strlen(path);
> +
> + node = get_subnode(node, path, seglen);
> + path += seglen + 1;
> + } while (node && slash);
> +
> + return node;
> +}
> +
> +QDTNode *qdt_get_node(QDTNode *root, const gchar *path)
> +{
> + g_assert(!root->parent);
> + g_assert(path[0] == '/');
> + return qdt_get_node_relative(root, path + 1);
> +}
> +
> +QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name)
> +{
> + QDTNode *new = qdt_new_node(name);
> +
> + new->parent = parent;
> + QTAILQ_INSERT_TAIL(&parent->children, new, sibling);
> + return new;
> +}
In case somebody ever tries to compile this with a C++ compiler ... it's
maybe better avoid using "new" as name for a variable.
> +/*
> + * Property functions
> + */
> +
> +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
> +{
> + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
> +
> + prop->name = g_strdup(name);
> + prop->len = len;
> + memcpy(prop->val, val, len);
> + return prop;
> +}
> +
> +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
Underscore at the end looks somewhat strange ... can't you simply drop that?
> +{
> + QDTProperty *prop;
> +
> + QTAILQ_FOREACH(prop, &node->properties, list) {
> + if (strcmp(prop->name, name) == 0) {
> + return prop;
> + }
> + }
> + return NULL;
> +}
> +
> +const QDTProperty *qdt_getprop(const QDTNode *node, const gchar *name)
> +{
> + return getprop_(node, name);
> +}
> +
> +void qdt_delprop(QDTNode *node, const gchar *name)
> +{
> + QDTProperty *prop = getprop_(node, name);
> +
> + if (prop) {
> + QTAILQ_REMOVE(&node->properties, prop, list);
> + g_free(prop->name);
> + g_free(prop);
> + }
> +}
> +
> +const QDTProperty *qdt_setprop(QDTNode *node, const gchar *name,
> + gconstpointer val, gsize len)
> +{
> + QDTProperty *prop;
> +
> + qdt_delprop(node, name);
> +
> + prop = g_malloc0(sizeof(*prop) + len);
> + prop->name = g_strdup(name);
> + prop->len = len;
> + memcpy(prop->val, val, len);
Can you replace the above four lines with qdt_new_property ?
> + QTAILQ_INSERT_TAIL(&node->properties, prop, list);
> + return prop;
> +}
> +
> +const QDTProperty *qdt_setprop_string(QDTNode *node, const gchar *name,
> + const gchar *val)
> +{
> + return qdt_setprop(node, name, val, strlen(val) + 1);
> +}
> +
> +const QDTProperty *qdt_setprop_cells_(QDTNode *node, const gchar *name,
> + const uint32_t *val, gsize len)
> +{
> + uint32_t swapval[len];
> + gsize i;
> +
> + for (i = 0; i < len; i++) {
> + swapval[i] = cpu_to_fdt32(val[i]);
> + }
> + return qdt_setprop(node, name, swapval, sizeof(swapval));
> +}
> +
> +const QDTProperty *qdt_setprop_u64s_(QDTNode *node, const char *name,
> + const uint64_t *val, gsize len)
> +{
> + uint64_t swapval[len];
> + gsize i;
> +
> + for (i = 0; i < len; i++) {
> + swapval[i] = cpu_to_fdt64(val[i]);
> + }
> + return qdt_setprop(node, name, swapval, sizeof(swapval));
> +}
> +
> +void qdt_set_phandle(QDTNode *node, uint32_t phandle)
> +{
> + g_assert((phandle != 0) && (phandle != (uint32_t)-1));
> + qdt_setprop_cells(node, "linux,phandle", phandle);
Do we still need "linux,phandle" nowadays? ... maybe that would be a
good point in time now to slowly get rid of this?
At least the ARM code seems to work already without that, and pseries
should also be fine without it (since SLOF replaces "phandle" and
"linux,phandle" anyway).
> + qdt_setprop_cells(node, "phandle", phandle);
> +}
> +
> +/*
> + * Whole tree functions
> + */
> +
> +static void qdt_flatten_node(void *fdt, QDTNode *node, Error **errp)
> +{
> + QDTProperty *prop;
> + QDTNode *subnode;
> + Error *local_err = NULL;
> + int ret;
> +
> + ret = fdt_begin_node(fdt, node->name);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_begin_node(): %s",
> + fdt_strerror(ret));
> + return;
> + }
> +
> + QTAILQ_FOREACH(prop, &node->properties, list) {
> + ret = fdt_property(fdt, prop->name, prop->val, prop->len);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_property(): %s",
> + fdt_strerror(ret));
> + return;
> + }
> + }
> +
> + QTAILQ_FOREACH(subnode, &node->children, sibling) {
> + qdt_flatten_node(fdt, subnode, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + }
> +
> + ret = fdt_end_node(fdt);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_end_node(): %s",
> + fdt_strerror(ret));
> + return;
> + }
> +}
> +
> +void *qdt_flatten(QDTNode *root, gsize bufsize, Error **errp)
> +{
> + void *fdt = g_malloc0(bufsize);
> + Error *local_err = NULL;
> + int ret;
So the caller has already to know here, how big the flattened device
tree will be at max? That's a somewhat cumbersome interface. Would it be
feasible to determine the size automatically somehow?
Or maybe at least make the caller provide the buffer to the fdt array...
then the caller provides both, buffer pointer and size. That would be
somewhat more consistent interface, I think.
> + assert(!root->parent); /* Should be a root node */
> +
> + ret = fdt_create(fdt, bufsize);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_create(): %s",
> + fdt_strerror(ret));
> + goto fail;
> + }
> +
> + ret = fdt_finish_reservemap(fdt);
> + if (ret < 0) {
> + error_setg(errp,
> + "Error flattening device tree: fdt_finish_reservemap(): %s",
> + fdt_strerror(ret));
> + goto fail;
> + }
> +
> + qdt_flatten_node(fdt, root, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + goto fail;
> + }
> +
> + ret = fdt_finish(fdt);
> + if (ret < 0) {
> + error_setg(errp, "Error flattening device tree: fdt_finish(): %s",
> + fdt_strerror(ret));
> + goto fail;
> + }
Maybe add a sanity check a la "fdt_totalsize(fdt) < bufsize" here and
abort on buffer overflow?
(or move such a check even into qdt_flatten_node ?)
> + return fdt;
> +
> +fail:
> + g_free(fdt);
> + return NULL;
> +}
Thomas
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 04/11] pseries: Make spapr_create_fdt_skel() get information from machine state
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 04/11] pseries: Make spapr_create_fdt_skel() get information from machine state David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
@ 2016-04-26 17:41 ` Thomas Huth
1 sibling, 0 replies; 44+ messages in thread
From: Thomas Huth @ 2016-04-26 17:41 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel
On 20.04.2016 04:33, David Gibson wrote:
> Currently spapr_create_fdt_skel() takes a bunch of individual parameters
> for various things it will put in the device tree. Some of these can
> already be taken directly from sPAPRMachineState. This patch alters it so
> that all of them can be taken from there, which will allow this code to
> be moved away from its current caller in future.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> hw/ppc/spapr.c | 81 ++++++++++++++++++++++----------------------------
> include/hw/ppc/spapr.h | 4 +++
> 2 files changed, 40 insertions(+), 45 deletions(-)
Reviewed-by: Thomas Huth <thuth@redhat.com>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
@ 2016-04-26 18:13 ` Thomas Huth
2016-04-27 6:07 ` David Gibson
1 sibling, 1 reply; 44+ messages in thread
From: Thomas Huth @ 2016-04-26 18:13 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel
On 20.04.2016 04:33, David Gibson wrote:
> Currently the pseries code builds a "skeleton" device tree at machine init
> time, then adds a bunch of stuff to it at reset. Over time, more and more
> logic has had to be moved from init to reset time, and there's really no
> advantage to doing any of it at init time.
>
> This patch removes the init time spapr_create_fdt_skel() and moves its
> logic into the reset time spapr_build_fdt(). There's still a fairly
> pointless divide between the "skeleton" logic (using libfdt serial-write
> functions) and the "tweak" logic (using libfdt random access functions)
> but at least it all happens at the same time, making further consolidation
> easier.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> hw/ppc/spapr.c | 398 ++++++++++++++++++++++++-------------------------
> include/hw/ppc/spapr.h | 1 -
> 2 files changed, 192 insertions(+), 207 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index da10136..6e1192f 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
...
> @@ -901,7 +702,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> hwaddr rtas_addr,
> hwaddr rtas_size)
> {
> - MachineState *machine = MACHINE(qdev_get_machine());
> + MachineState *machine = MACHINE(spapr);
> sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
> const char *boot_device = machine->boot_order;
> int ret, i;
> @@ -909,11 +710,200 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> char *bootlist;
> void *fdt;
> sPAPRPHBState *phb;
> + uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
> + uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
> + GString *hypertas = g_string_sized_new(256);
> + GString *qemu_hypertas = g_string_sized_new(256);
> + uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
> + uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
> + unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
> + char *buf;
> +
> + add_str(hypertas, "hcall-pft");
> + add_str(hypertas, "hcall-term");
> + add_str(hypertas, "hcall-dabr");
> + add_str(hypertas, "hcall-interrupt");
> + add_str(hypertas, "hcall-tce");
> + add_str(hypertas, "hcall-vio");
> + add_str(hypertas, "hcall-splpar");
> + add_str(hypertas, "hcall-bulk");
> + add_str(hypertas, "hcall-set-mode");
> + add_str(qemu_hypertas, "hcall-memop1");
> +
> + fdt = g_malloc0(FDT_MAX_SIZE);
> + _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
> +
> + if (spapr->kernel_size) {
> + _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
> + spapr->kernel_size)));
> + }
> + if (spapr->initrd_size) {
> + _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
> + spapr->initrd_size)));
> + }
> + _FDT((fdt_finish_reservemap(fdt)));
> +
> + /* Root node */
> + _FDT((fdt_begin_node(fdt, "")));
> + _FDT((fdt_property_string(fdt, "device_type", "chrp")));
> + _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
> + _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
> +
> + /*
> + * Add info to guest to indentify which host is it being run on
> + * and what is the uuid of the guest
> + */
> + if (kvmppc_get_host_model(&buf)) {
> + _FDT((fdt_property_string(fdt, "host-model", buf)));
> + g_free(buf);
> + }
> + if (kvmppc_get_host_serial(&buf)) {
> + _FDT((fdt_property_string(fdt, "host-serial", buf)));
> + g_free(buf);
> + }
>
> - fdt = g_malloc(FDT_MAX_SIZE);
> + buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
> + qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
> + qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
> + qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
> + qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
> + qemu_uuid[14], qemu_uuid[15]);
> +
> + _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
> + if (qemu_uuid_set) {
> + _FDT((fdt_property_string(fdt, "system-id", buf)));
> + }
> + g_free(buf);
> +
> + if (qemu_get_vm_name()) {
> + _FDT((fdt_property_string(fdt, "ibm,partition-name",
> + qemu_get_vm_name())));
> + }
> +
> + _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
> + _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
> +
> + /* /chosen */
> + _FDT((fdt_begin_node(fdt, "chosen")));
> +
> + /* Set Form1_affinity */
> + _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
> +
> + _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
> + _FDT((fdt_property(fdt, "linux,initrd-start",
> + &start_prop, sizeof(start_prop))));
> + _FDT((fdt_property(fdt, "linux,initrd-end",
> + &end_prop, sizeof(end_prop))));
> + if (spapr->kernel_size) {
> + uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
> + cpu_to_be64(spapr->kernel_size) };
> +
> + _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
> + if (spapr->kernel_le) {
> + _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
> + }
> + }
> + if (boot_menu) {
> + _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
> + }
> + _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
> + _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
> + _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
> +
> + _FDT((fdt_end_node(fdt)));
> +
> + /* RTAS */
> + _FDT((fdt_begin_node(fdt, "rtas")));
> +
> + if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> + add_str(hypertas, "hcall-multi-tce");
> + }
> + _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
> + hypertas->len)));
> + g_string_free(hypertas, TRUE);
> + _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
> + qemu_hypertas->len)));
> + g_string_free(qemu_hypertas, TRUE);
> +
> + _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
> + refpoints, sizeof(refpoints))));
> +
> + _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
> + _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
> + RTAS_EVENT_SCAN_RATE)));
> +
> + if (msi_nonbroken) {
> + _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
> + }
> +
> + /*
> + * According to PAPR, rtas ibm,os-term does not guarantee a return
> + * back to the guest cpu.
> + *
> + * While an additional ibm,extended-os-term property indicates that
> + * rtas call return will always occur. Set this property.
> + */
> + _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
> +
> + _FDT((fdt_end_node(fdt)));
> +
> + /* interrupt controller */
> + _FDT((fdt_begin_node(fdt, "interrupt-controller")));
> +
> + _FDT((fdt_property_string(fdt, "device_type",
> + "PowerPC-External-Interrupt-Presentation")));
> + _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
> + _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> + _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
> + interrupt_server_ranges_prop,
> + sizeof(interrupt_server_ranges_prop))));
> + _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> + _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
> + _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
> +
> + _FDT((fdt_end_node(fdt)));
> +
> + /* vdevice */
> + _FDT((fdt_begin_node(fdt, "vdevice")));
> +
> + _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
> + _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
> + _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
> + _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
> + _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
> + _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> +
> + _FDT((fdt_end_node(fdt)));
> +
> + /* event-sources */
> + spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
> +
> + /* /hypervisor node */
> + if (kvm_enabled()) {
> + uint8_t hypercall[16];
> +
> + /* indicate KVM hypercall interface */
> + _FDT((fdt_begin_node(fdt, "hypervisor")));
> + _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
> + if (kvmppc_has_cap_fixup_hcalls()) {
> + /*
> + * Older KVM versions with older guest kernels were broken with the
> + * magic page, don't allow the guest to map it.
> + */
> + if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
> + sizeof(hypercall))) {
> + _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
> + sizeof(hypercall))));
> + }
> + }
> + _FDT((fdt_end_node(fdt)));
> + }
> +
> + _FDT((fdt_end_node(fdt))); /* close root node */
> + _FDT((fdt_finish(fdt)));
The old spapr_finalize_fdt() was already quite big - if you now move all
this code hiere, this function becomes a really bloated. So while you're
reworking all this stuff ... maybe it would be nicer to split the big
chunk into separate functions, e.g. one function for each device tree node?
> /* open out the base tree into a temp buffer for the final tweaks */
> - _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
> + _FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
Can fdt_open_into deal with input = output pointer? I haven't checked
it, but that looks somewhat strange. Is this line still required at all
after you moved to code here?
> ret = spapr_populate_memory(spapr, fdt);
> if (ret < 0) {
> @@ -1980,10 +1970,6 @@ static void ppc_spapr_init(MachineState *machine)
> register_savevm_live(NULL, "spapr/htab", -1, 1,
> &savevm_htab_handlers, spapr);
>
> - /* Prepare the device tree */
> - spapr->fdt_skel = spapr_create_fdt_skel(spapr);
> - assert(spapr->fdt_skel != NULL);
> -
> /* used by RTAS */
> QTAILQ_INIT(&spapr->ccs_list);
> qemu_register_reset(spapr_ccs_reset_hook, spapr);
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 88f29a8..cd72586 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -62,7 +62,6 @@ struct sPAPRMachineState {
> bool kernel_le;
> uint32_t initrd_base;
> long initrd_size;
> - void *fdt_skel;
> uint64_t rtc_offset; /* Now used only during incoming migration */
> struct PPCTimebase tb;
> bool has_graphics;
Thomas
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-26 11:00 ` Thomas Huth
@ 2016-04-27 6:02 ` David Gibson
2016-04-27 6:43 ` Markus Armbruster
0 siblings, 1 reply; 44+ messages in thread
From: David Gibson @ 2016-04-27 6:02 UTC (permalink / raw)
To: Thomas Huth; +Cc: agraf, crosthwaite.peter, aik, qemu-ppc, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 11518 bytes --]
On Tue, Apr 26, 2016 at 01:00:06PM +0200, Thomas Huth wrote:
> On 20.04.2016 04:33, David Gibson wrote:
> ...
> > This patch introduces a new utility library "qdt" for runtime
> > manipulation of device trees. The intention is that machine type code
> > can use these routines to construct the device tree conveniently,
> > using a pointer-based representation doesn't have the limitations
> > above. They can then use qdt_flatten() to convert the completed tree
> > to fdt format as a single O(n) operation to pass to the guest.
>
> Good idea, the FDT format itself is really not very well suited for
> dynamic manipulations...
>
> ...
> > diff --git a/util/qdt.c b/util/qdt.c
> > new file mode 100644
> > index 0000000..e3a449a
> > --- /dev/null
> > +++ b/util/qdt.c
> > @@ -0,0 +1,262 @@
> > +/*
> > + * Functions for manipulating IEEE1275 (Open Firmware) style device
> > + * trees.
>
> What does QDT stand for? Maybe add that in the description here.
"QEMU Device Tree" I guess? Really I was just looking for something
similar but not the same as fdt, and short.
> > + * Copyright David Gibson, Red Hat Inc. 2016
> > + *
> > + * This work is licensed unter the GNU GPL version 2 or (at your
> > + * option) any later version.
> > + */
> > +
> > +#include <libfdt.h>
> > +#include <stdbool.h>
> > +
> > +#include "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "qemu/qdt.h"
> > +#include "qemu/error-report.h"
> > +
> > +/*
> > + * Node functions
> > + */
> > +
> > +QDTNode *qdt_new_node(const gchar *name)
> > +{
> > + QDTNode *node = g_new0(QDTNode, 1);
> > +
> > + g_assert(!strchr(name, '/'));
> > +
> > + node->name = g_strdup(name);
> > + QTAILQ_INIT(&node->properties);
> > + QTAILQ_INIT(&node->children);
> > +
> > + return node;
> > +}
> > +
> > +static QDTNode *get_subnode(QDTNode *parent, const gchar *name, size_t namelen)
> > +{
> > + QDTNode *child;
> > +
> > + g_assert(!memchr(name, '/', namelen));
> > +
> > + QTAILQ_FOREACH(child, &parent->children, sibling) {
> > + if ((strlen(child->name) == namelen)
> > + && (memcmp(child->name, name, namelen) == 0)) {
>
> Too many parenthesis for my taste ;-)
>
> > + return child;
> > + }
> > + }
> > +
> > + return NULL;
> > +}
> > +
> > +QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path)
> > +{
> > + const gchar *slash;
> > + gsize seglen;
> > +
> > + do {
> > + slash = strchr(path, '/');
> > + seglen = slash ? slash - path : strlen(path);
> > +
> > + node = get_subnode(node, path, seglen);
> > + path += seglen + 1;
> > + } while (node && slash);
> > +
> > + return node;
> > +}
> > +
> > +QDTNode *qdt_get_node(QDTNode *root, const gchar *path)
> > +{
> > + g_assert(!root->parent);
> > + g_assert(path[0] == '/');
> > + return qdt_get_node_relative(root, path + 1);
> > +}
> > +
> > +QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name)
> > +{
> > + QDTNode *new = qdt_new_node(name);
> > +
> > + new->parent = parent;
> > + QTAILQ_INSERT_TAIL(&parent->children, new, sibling);
> > + return new;
> > +}
>
> In case somebody ever tries to compile this with a C++ compiler ... it's
> maybe better avoid using "new" as name for a variable.
Good point, will change.
> > +/*
> > + * Property functions
> > + */
> > +
> > +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
> > +{
> > + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
> > +
> > + prop->name = g_strdup(name);
> > + prop->len = len;
> > + memcpy(prop->val, val, len);
> > + return prop;
> > +}
> > +
> > +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
>
> Underscore at the end looks somewhat strange ... can't you simply drop that?
Well.. the idea was that the _ versions are the "internal" ones,
whereas external users will generally use the non-underscore version
(in this case the only difference is that the external one returns a
const pointer).
I don't particularly like that convention, so feel free to suggest
something better.
> > +{
> > + QDTProperty *prop;
> > +
> > + QTAILQ_FOREACH(prop, &node->properties, list) {
> > + if (strcmp(prop->name, name) == 0) {
> > + return prop;
> > + }
> > + }
> > + return NULL;
> > +}
> > +
> > +const QDTProperty *qdt_getprop(const QDTNode *node, const gchar *name)
> > +{
> > + return getprop_(node, name);
> > +}
> > +
> > +void qdt_delprop(QDTNode *node, const gchar *name)
> > +{
> > + QDTProperty *prop = getprop_(node, name);
> > +
> > + if (prop) {
> > + QTAILQ_REMOVE(&node->properties, prop, list);
> > + g_free(prop->name);
> > + g_free(prop);
> > + }
> > +}
> > +
> > +const QDTProperty *qdt_setprop(QDTNode *node, const gchar *name,
> > + gconstpointer val, gsize len)
> > +{
> > + QDTProperty *prop;
> > +
> > + qdt_delprop(node, name);
> > +
> > + prop = g_malloc0(sizeof(*prop) + len);
> > + prop->name = g_strdup(name);
> > + prop->len = len;
> > + memcpy(prop->val, val, len);
>
> Can you replace the above four lines with qdt_new_property ?
Actually, qdt_new_property() is a leftover from an approach I ended up
not liking, I should just remove it.
> > + QTAILQ_INSERT_TAIL(&node->properties, prop, list);
> > + return prop;
> > +}
> > +
> > +const QDTProperty *qdt_setprop_string(QDTNode *node, const gchar *name,
> > + const gchar *val)
> > +{
> > + return qdt_setprop(node, name, val, strlen(val) + 1);
> > +}
> > +
> > +const QDTProperty *qdt_setprop_cells_(QDTNode *node, const gchar *name,
> > + const uint32_t *val, gsize len)
> > +{
> > + uint32_t swapval[len];
> > + gsize i;
> > +
> > + for (i = 0; i < len; i++) {
> > + swapval[i] = cpu_to_fdt32(val[i]);
> > + }
> > + return qdt_setprop(node, name, swapval, sizeof(swapval));
> > +}
> > +
> > +const QDTProperty *qdt_setprop_u64s_(QDTNode *node, const char *name,
> > + const uint64_t *val, gsize len)
> > +{
> > + uint64_t swapval[len];
> > + gsize i;
> > +
> > + for (i = 0; i < len; i++) {
> > + swapval[i] = cpu_to_fdt64(val[i]);
> > + }
> > + return qdt_setprop(node, name, swapval, sizeof(swapval));
> > +}
> > +
> > +void qdt_set_phandle(QDTNode *node, uint32_t phandle)
> > +{
> > + g_assert((phandle != 0) && (phandle != (uint32_t)-1));
> > + qdt_setprop_cells(node, "linux,phandle", phandle);
>
> Do we still need "linux,phandle" nowadays? ... maybe that would be a
> good point in time now to slowly get rid of this?
> At least the ARM code seems to work already without that, and pseries
> should also be fine without it (since SLOF replaces "phandle" and
> "linux,phandle" anyway).
Erm.. maybe. IIRC the addition of support for the new property to the
early boot kernel code on Power was surprisingly late, so it seems
safer to include it, but, we can check.
> > + qdt_setprop_cells(node, "phandle", phandle);
> > +}
> > +
> > +/*
> > + * Whole tree functions
> > + */
> > +
> > +static void qdt_flatten_node(void *fdt, QDTNode *node, Error **errp)
> > +{
> > + QDTProperty *prop;
> > + QDTNode *subnode;
> > + Error *local_err = NULL;
> > + int ret;
> > +
> > + ret = fdt_begin_node(fdt, node->name);
> > + if (ret < 0) {
> > + error_setg(errp, "Error flattening device tree: fdt_begin_node(): %s",
> > + fdt_strerror(ret));
> > + return;
> > + }
> > +
> > + QTAILQ_FOREACH(prop, &node->properties, list) {
> > + ret = fdt_property(fdt, prop->name, prop->val, prop->len);
> > + if (ret < 0) {
> > + error_setg(errp, "Error flattening device tree: fdt_property(): %s",
> > + fdt_strerror(ret));
> > + return;
> > + }
> > + }
> > +
> > + QTAILQ_FOREACH(subnode, &node->children, sibling) {
> > + qdt_flatten_node(fdt, subnode, &local_err);
> > + if (local_err) {
> > + error_propagate(errp, local_err);
> > + return;
> > + }
> > + }
> > +
> > + ret = fdt_end_node(fdt);
> > + if (ret < 0) {
> > + error_setg(errp, "Error flattening device tree: fdt_end_node(): %s",
> > + fdt_strerror(ret));
> > + return;
> > + }
> > +}
> > +
> > +void *qdt_flatten(QDTNode *root, gsize bufsize, Error **errp)
> > +{
> > + void *fdt = g_malloc0(bufsize);
> > + Error *local_err = NULL;
> > + int ret;
>
> So the caller has already to know here, how big the flattened device
> tree will be at max? That's a somewhat cumbersome interface. Would it be
> feasible to determine the size automatically somehow?
Yes, I was planningto add an autosizing flatten interface, but I
wanted to get the basic concept reviewed before I bothered
implementing that. It shouldn't be that hard - just realloc()
whenever one of the FDT calls returns -FDT_ERR_NOSPACE.
> Or maybe at least make the caller provide the buffer to the fdt array...
> then the caller provides both, buffer pointer and size. That would be
> somewhat more consistent interface, I think.
Well, I was thinking that we could have the autosizing interface in
the same function by redefining that as a max size, and having 0 or -1
mean no maximum.
> > + assert(!root->parent); /* Should be a root node */
> > +
> > + ret = fdt_create(fdt, bufsize);
> > + if (ret < 0) {
> > + error_setg(errp, "Error flattening device tree: fdt_create(): %s",
> > + fdt_strerror(ret));
> > + goto fail;
> > + }
> > +
> > + ret = fdt_finish_reservemap(fdt);
> > + if (ret < 0) {
> > + error_setg(errp,
> > + "Error flattening device tree: fdt_finish_reservemap(): %s",
> > + fdt_strerror(ret));
> > + goto fail;
> > + }
> > +
> > + qdt_flatten_node(fdt, root, &local_err);
> > + if (local_err) {
> > + error_propagate(errp, local_err);
> > + goto fail;
> > + }
> > +
> > + ret = fdt_finish(fdt);
> > + if (ret < 0) {
> > + error_setg(errp, "Error flattening device tree: fdt_finish(): %s",
> > + fdt_strerror(ret));
> > + goto fail;
> > + }
>
> Maybe add a sanity check a la "fdt_totalsize(fdt) < bufsize" here and
> abort on buffer overflow?
There's really no point - the fdt functions can't succeed if they
overflow the buffer space, so we will have already tripped an error.
The only libfdt functions which will *ever* change fdt_totalsize() are
fdt_create(), fdt_open_int(), fdt_finish() and fdt_pack() and the last
two can only ever reduce it, never increase it.
> (or move such a check even into qdt_flatten_node ?)
>
> > + return fdt;
> > +
> > +fail:
> > + g_free(fdt);
> > + return NULL;
> > +}
>
> Thomas
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time
2016-04-26 18:13 ` Thomas Huth
@ 2016-04-27 6:07 ` David Gibson
0 siblings, 0 replies; 44+ messages in thread
From: David Gibson @ 2016-04-27 6:07 UTC (permalink / raw)
To: Thomas Huth; +Cc: agraf, crosthwaite.peter, aik, qemu-ppc, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 12642 bytes --]
On Tue, Apr 26, 2016 at 08:13:21PM +0200, Thomas Huth wrote:
> On 20.04.2016 04:33, David Gibson wrote:
> > Currently the pseries code builds a "skeleton" device tree at machine init
> > time, then adds a bunch of stuff to it at reset. Over time, more and more
> > logic has had to be moved from init to reset time, and there's really no
> > advantage to doing any of it at init time.
> >
> > This patch removes the init time spapr_create_fdt_skel() and moves its
> > logic into the reset time spapr_build_fdt(). There's still a fairly
> > pointless divide between the "skeleton" logic (using libfdt serial-write
> > functions) and the "tweak" logic (using libfdt random access functions)
> > but at least it all happens at the same time, making further consolidation
> > easier.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> > hw/ppc/spapr.c | 398 ++++++++++++++++++++++++-------------------------
> > include/hw/ppc/spapr.h | 1 -
> > 2 files changed, 192 insertions(+), 207 deletions(-)
> >
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index da10136..6e1192f 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> ...
> > @@ -901,7 +702,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> > hwaddr rtas_addr,
> > hwaddr rtas_size)
> > {
> > - MachineState *machine = MACHINE(qdev_get_machine());
> > + MachineState *machine = MACHINE(spapr);
> > sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
> > const char *boot_device = machine->boot_order;
> > int ret, i;
> > @@ -909,11 +710,200 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> > char *bootlist;
> > void *fdt;
> > sPAPRPHBState *phb;
> > + uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
> > + uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
> > + GString *hypertas = g_string_sized_new(256);
> > + GString *qemu_hypertas = g_string_sized_new(256);
> > + uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
> > + uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
> > + unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
> > + char *buf;
> > +
> > + add_str(hypertas, "hcall-pft");
> > + add_str(hypertas, "hcall-term");
> > + add_str(hypertas, "hcall-dabr");
> > + add_str(hypertas, "hcall-interrupt");
> > + add_str(hypertas, "hcall-tce");
> > + add_str(hypertas, "hcall-vio");
> > + add_str(hypertas, "hcall-splpar");
> > + add_str(hypertas, "hcall-bulk");
> > + add_str(hypertas, "hcall-set-mode");
> > + add_str(qemu_hypertas, "hcall-memop1");
> > +
> > + fdt = g_malloc0(FDT_MAX_SIZE);
> > + _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
> > +
> > + if (spapr->kernel_size) {
> > + _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
> > + spapr->kernel_size)));
> > + }
> > + if (spapr->initrd_size) {
> > + _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
> > + spapr->initrd_size)));
> > + }
> > + _FDT((fdt_finish_reservemap(fdt)));
> > +
> > + /* Root node */
> > + _FDT((fdt_begin_node(fdt, "")));
> > + _FDT((fdt_property_string(fdt, "device_type", "chrp")));
> > + _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
> > + _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
> > +
> > + /*
> > + * Add info to guest to indentify which host is it being run on
> > + * and what is the uuid of the guest
> > + */
> > + if (kvmppc_get_host_model(&buf)) {
> > + _FDT((fdt_property_string(fdt, "host-model", buf)));
> > + g_free(buf);
> > + }
> > + if (kvmppc_get_host_serial(&buf)) {
> > + _FDT((fdt_property_string(fdt, "host-serial", buf)));
> > + g_free(buf);
> > + }
> >
> > - fdt = g_malloc(FDT_MAX_SIZE);
> > + buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
> > + qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
> > + qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
> > + qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
> > + qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
> > + qemu_uuid[14], qemu_uuid[15]);
> > +
> > + _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
> > + if (qemu_uuid_set) {
> > + _FDT((fdt_property_string(fdt, "system-id", buf)));
> > + }
> > + g_free(buf);
> > +
> > + if (qemu_get_vm_name()) {
> > + _FDT((fdt_property_string(fdt, "ibm,partition-name",
> > + qemu_get_vm_name())));
> > + }
> > +
> > + _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
> > + _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
> > +
> > + /* /chosen */
> > + _FDT((fdt_begin_node(fdt, "chosen")));
> > +
> > + /* Set Form1_affinity */
> > + _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
> > +
> > + _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
> > + _FDT((fdt_property(fdt, "linux,initrd-start",
> > + &start_prop, sizeof(start_prop))));
> > + _FDT((fdt_property(fdt, "linux,initrd-end",
> > + &end_prop, sizeof(end_prop))));
> > + if (spapr->kernel_size) {
> > + uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
> > + cpu_to_be64(spapr->kernel_size) };
> > +
> > + _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
> > + if (spapr->kernel_le) {
> > + _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
> > + }
> > + }
> > + if (boot_menu) {
> > + _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
> > + }
> > + _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
> > + _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
> > + _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
> > +
> > + _FDT((fdt_end_node(fdt)));
> > +
> > + /* RTAS */
> > + _FDT((fdt_begin_node(fdt, "rtas")));
> > +
> > + if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> > + add_str(hypertas, "hcall-multi-tce");
> > + }
> > + _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
> > + hypertas->len)));
> > + g_string_free(hypertas, TRUE);
> > + _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
> > + qemu_hypertas->len)));
> > + g_string_free(qemu_hypertas, TRUE);
> > +
> > + _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
> > + refpoints, sizeof(refpoints))));
> > +
> > + _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
> > + _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
> > + RTAS_EVENT_SCAN_RATE)));
> > +
> > + if (msi_nonbroken) {
> > + _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
> > + }
> > +
> > + /*
> > + * According to PAPR, rtas ibm,os-term does not guarantee a return
> > + * back to the guest cpu.
> > + *
> > + * While an additional ibm,extended-os-term property indicates that
> > + * rtas call return will always occur. Set this property.
> > + */
> > + _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
> > +
> > + _FDT((fdt_end_node(fdt)));
> > +
> > + /* interrupt controller */
> > + _FDT((fdt_begin_node(fdt, "interrupt-controller")));
> > +
> > + _FDT((fdt_property_string(fdt, "device_type",
> > + "PowerPC-External-Interrupt-Presentation")));
> > + _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
> > + _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> > + _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
> > + interrupt_server_ranges_prop,
> > + sizeof(interrupt_server_ranges_prop))));
> > + _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> > + _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
> > + _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
> > +
> > + _FDT((fdt_end_node(fdt)));
> > +
> > + /* vdevice */
> > + _FDT((fdt_begin_node(fdt, "vdevice")));
> > +
> > + _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
> > + _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
> > + _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
> > + _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
> > + _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
> > + _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> > +
> > + _FDT((fdt_end_node(fdt)));
> > +
> > + /* event-sources */
> > + spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
> > +
> > + /* /hypervisor node */
> > + if (kvm_enabled()) {
> > + uint8_t hypercall[16];
> > +
> > + /* indicate KVM hypercall interface */
> > + _FDT((fdt_begin_node(fdt, "hypervisor")));
> > + _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
> > + if (kvmppc_has_cap_fixup_hcalls()) {
> > + /*
> > + * Older KVM versions with older guest kernels were broken with the
> > + * magic page, don't allow the guest to map it.
> > + */
> > + if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
> > + sizeof(hypercall))) {
> > + _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
> > + sizeof(hypercall))));
> > + }
> > + }
> > + _FDT((fdt_end_node(fdt)));
> > + }
> > +
> > + _FDT((fdt_end_node(fdt))); /* close root node */
> > + _FDT((fdt_finish(fdt)));
>
> The old spapr_finalize_fdt() was already quite big - if you now move all
> this code hiere, this function becomes a really bloated. So while you're
> reworking all this stuff ... maybe it would be nicer to split the big
> chunk into separate functions, e.g. one function for each device tree node?
Perhaps - it's all in sequence code, though, so I'm not particularly
fussed by it being long. It will also shrink a bit as we fold
together the fdt and qdt code.
> > /* open out the base tree into a temp buffer for the final tweaks */
> > - _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE)));
> > + _FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
>
> Can fdt_open_into deal with input = output pointer? I haven't checked
> it, but that looks somewhat strange. Is this line still required at all
> after you moved to code here?
Yes, it absolutely can. Looks like I never got around to writing a
doc block for fdt_open_into() but it was always designed to handle
both the expanding in place and expanding to elsewhere cases.
> > ret = spapr_populate_memory(spapr, fdt);
> > if (ret < 0) {
> > @@ -1980,10 +1970,6 @@ static void ppc_spapr_init(MachineState *machine)
> > register_savevm_live(NULL, "spapr/htab", -1, 1,
> > &savevm_htab_handlers, spapr);
> >
> > - /* Prepare the device tree */
> > - spapr->fdt_skel = spapr_create_fdt_skel(spapr);
> > - assert(spapr->fdt_skel != NULL);
> > -
> > /* used by RTAS */
> > QTAILQ_INIT(&spapr->ccs_list);
> > qemu_register_reset(spapr_ccs_reset_hook, spapr);
> > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> > index 88f29a8..cd72586 100644
> > --- a/include/hw/ppc/spapr.h
> > +++ b/include/hw/ppc/spapr.h
> > @@ -62,7 +62,6 @@ struct sPAPRMachineState {
> > bool kernel_le;
> > uint32_t initrd_base;
> > long initrd_size;
> > - void *fdt_skel;
> > uint64_t rtc_offset; /* Now used only during incoming migration */
> > struct PPCTimebase tb;
> > bool has_graphics;
>
> Thomas
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 08/11] pseries: Start using qdt library for building device tree
2016-04-21 4:04 ` Alexey Kardashevskiy
@ 2016-04-27 6:13 ` David Gibson
0 siblings, 0 replies; 44+ messages in thread
From: David Gibson @ 2016-04-27 6:13 UTC (permalink / raw)
To: Alexey Kardashevskiy; +Cc: agraf, crosthwaite.peter, qemu-ppc, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 18735 bytes --]
On Thu, Apr 21, 2016 at 02:04:16PM +1000, Alexey Kardashevskiy wrote:
> On 04/20/2016 12:33 PM, David Gibson wrote:
> >This starts the process of converting the pseries machine type to use
> >the qdt library code to build the guest's device tree instead of
> >working directly and awkwardly with the flattened device tree format.
> >
> >For now we just convert the first section of spapr_build_fdt() which
> >creates a tree sequentially, so that it builds the qdt then flattens
> >it. This leaves a lot of code which still manipulates the fdt after
> >that point, but the intention is to convert those to work with the qdt
> >format in future.
> >
> >Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
>
>
> 9 patches or 11 look good as they do one right thing at the time.
>
> But this one does:
> 1. replace _FDT() with qdt_setprop_xxx
> 2. "consolidates" spapr_events_fdt_skel() (other code movements got own
> patches but not this one)
> 3. moves bits around like the hyperrtas property composer.
>
> This all makes it harder to verify that you have not lost anything in
> transition...
Yeah, there is a fair bit here; the individual components didn't see
very sensible on their own. I'll take another look on the respin.
> I'd also expect this patch to be the second (right after "qdt:
> IEEE1275-style device tree utility code") or after all "consolidation"
> patches (this would make even more sense), and this patch would convert all
> _FDTs, and then remove _FDT() macro. Or "in future" from the commit log
> means "nearest future"? :)
I wanted to put the intermediate patches first so I didn't need to
port some uglies fromt the old approach to the new before removing
them.
And yes, I want to convert all (or at least, nearly all) the fdt code
in spapr, but I wanted to get some review of the overall concept
before I converted everything. VIO and PCI will both be a bit fiddly.
> btw after all these device tree rendering code gathered in one place - how
> many of the original justification points are still valid? Persistent
> handles or being slow should not be problems anymore (as it is sequential
> device tree rendering, without reordering).
>
>
> >---
> > hw/ppc/spapr.c | 236 ++++++++++++++++++++++++-------------------------
> > hw/ppc/spapr_events.c | 19 ----
> > include/hw/ppc/spapr.h | 1 -
> > 3 files changed, 117 insertions(+), 139 deletions(-)
> >
> >diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> >index aef44a2..d04d403 100644
> >--- a/hw/ppc/spapr.c
> >+++ b/hw/ppc/spapr.c
> >@@ -66,6 +66,8 @@
> > #include "hw/compat.h"
> > #include "qemu/cutils.h"
> >
> >+#include "qemu/qdt.h"
> >+
> > #include <libfdt.h>
> >
> > /* SLOF memory layout:
> >@@ -710,47 +712,27 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> > char *bootlist;
> > void *fdt;
> > sPAPRPHBState *phb;
> >- uint32_t start_prop = cpu_to_be32(spapr->initrd_base);
> >- uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size);
> >- GString *hypertas = g_string_sized_new(256);
> >- GString *qemu_hypertas = g_string_sized_new(256);
> >- uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
> >- uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)};
> >- unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80};
> > char *buf;
> >+ QDTNode *root;
> >
> >- add_str(hypertas, "hcall-pft");
> >- add_str(hypertas, "hcall-term");
> >- add_str(hypertas, "hcall-dabr");
> >- add_str(hypertas, "hcall-interrupt");
> >- add_str(hypertas, "hcall-tce");
> >- add_str(hypertas, "hcall-vio");
> >- add_str(hypertas, "hcall-splpar");
> >- add_str(hypertas, "hcall-bulk");
> >- add_str(hypertas, "hcall-set-mode");
> >- add_str(qemu_hypertas, "hcall-memop1");
> >-
> >- fdt = g_malloc0(FDT_MAX_SIZE);
> >- _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
> >+ root = qdt_new_tree();
> >
> >- _FDT((fdt_finish_reservemap(fdt)));
> >+ /* / (root node) */
> >
> >- /* Root node */
> >- _FDT((fdt_begin_node(fdt, "")));
> >- _FDT((fdt_property_string(fdt, "device_type", "chrp")));
> >- _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
> >- _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
> >+ qdt_setprop_string(root, "device_type", "chrp");
> >+ qdt_setprop_string(root, "model", "IBM pSeries (emulated by qemu)");
> >+ qdt_setprop_string(root, "compatible", "qemu,pseries");
> >
> > /*
> > * Add info to guest to indentify which host is it being run on
> > * and what is the uuid of the guest
> > */
> > if (kvmppc_get_host_model(&buf)) {
> >- _FDT((fdt_property_string(fdt, "host-model", buf)));
> >+ qdt_setprop_string(root, "host-model", buf);
> > g_free(buf);
> > }
> > if (kvmppc_get_host_serial(&buf)) {
> >- _FDT((fdt_property_string(fdt, "host-serial", buf)));
> >+ qdt_setprop_string(root, "host-serial", buf);
> > g_free(buf);
> > }
> >
> >@@ -761,138 +743,154 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> > qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
> > qemu_uuid[14], qemu_uuid[15]);
> >
> >- _FDT((fdt_property_string(fdt, "vm,uuid", buf)));
> >+ qdt_setprop_string(root, "vm,uuid", buf);
> > if (qemu_uuid_set) {
> >- _FDT((fdt_property_string(fdt, "system-id", buf)));
> >+ qdt_setprop_string(root, "system-id", buf);
> > }
> > g_free(buf);
> >
> > if (qemu_get_vm_name()) {
> >- _FDT((fdt_property_string(fdt, "ibm,partition-name",
> >- qemu_get_vm_name())));
> >+ qdt_setprop_string(root, "ibm,partition-name", qemu_get_vm_name());
> > }
> >
> >- _FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
> >- _FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
> >+ qdt_setprop_cells(root, "#address-cells", 0x2);
> >+ qdt_setprop_cells(root, "#size-cells", 0x2);
> >
> > /* /chosen */
> >- _FDT((fdt_begin_node(fdt, "chosen")));
> >-
> >- /* Set Form1_affinity */
> >- _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5))));
> >-
> >- _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline)));
> >- _FDT((fdt_property(fdt, "linux,initrd-start",
> >- &start_prop, sizeof(start_prop))));
> >- _FDT((fdt_property(fdt, "linux,initrd-end",
> >- &end_prop, sizeof(end_prop))));
> >- if (spapr->kernel_size) {
> >- uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
> >- cpu_to_be64(spapr->kernel_size) };
> >-
> >- _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop))));
> >- if (spapr->kernel_le) {
> >- _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0)));
> >+ {
> >+ QDTNode *chosen = qdt_add_subnode(root, "chosen");
> >+
> >+ /* Set Form1_affinity */
> >+ qdt_setprop_bytes(chosen, "ibm,architecture-vec-5",
> >+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x80);
> >+
> >+ qdt_setprop_string(chosen, "bootargs", machine->kernel_cmdline);
> >+ qdt_setprop_cells(chosen, "linux,initrd-start",
> >+ spapr->initrd_base);
> >+ qdt_setprop_cells(chosen, "linux,initrd-end",
> >+ spapr->initrd_base + spapr->initrd_size);
> >+ if (spapr->kernel_size) {
> >+ qdt_setprop_u64s(chosen, "qemu,boot-kernel",
> >+ KERNEL_LOAD_ADDR, spapr->kernel_size);
> >+ if (spapr->kernel_le) {
> >+ qdt_setprop_empty(chosen, "qemu,boot-kernel-le");
> >+ }
> > }
> >+ if (boot_menu) {
> >+ qdt_setprop_cells(chosen, "qemu,boot-menu", boot_menu);
> >+ }
> >+ qdt_setprop_cells(chosen, "qemu,graphic-width", graphic_width);
> >+ qdt_setprop_cells(chosen, "qemu,graphic-height", graphic_height);
> >+ qdt_setprop_cells(chosen, "qemu,graphic-depth", graphic_depth);
> > }
> >- if (boot_menu) {
> >- _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu)));
> >- }
> >- _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width)));
> >- _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height)));
> >- _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth)));
> >-
> >- _FDT((fdt_end_node(fdt)));
> >
> > /* RTAS */
> >- _FDT((fdt_begin_node(fdt, "rtas")));
> >+ {
> >+ QDTNode *rtas = qdt_add_subnode(root, "rtas");
> >+ GString *hypertas = g_string_sized_new(256);
> >+ GString *qemu_hypertas = g_string_sized_new(256);
> >
> >- if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> >- add_str(hypertas, "hcall-multi-tce");
> >- }
> >- _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
> >- hypertas->len)));
> >- g_string_free(hypertas, TRUE);
> >- _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
> >- qemu_hypertas->len)));
> >- g_string_free(qemu_hypertas, TRUE);
> >+ add_str(hypertas, "hcall-pft");
> >+ add_str(hypertas, "hcall-term");
> >+ add_str(hypertas, "hcall-dabr");
> >+ add_str(hypertas, "hcall-interrupt");
> >+ add_str(hypertas, "hcall-tce");
> >+ add_str(hypertas, "hcall-vio");
> >+ add_str(hypertas, "hcall-splpar");
> >+ add_str(hypertas, "hcall-bulk");
> >+ add_str(hypertas, "hcall-set-mode");
> >+ add_str(qemu_hypertas, "hcall-memop1");
> >
> >- _FDT((fdt_property(fdt, "ibm,associativity-reference-points",
> >- refpoints, sizeof(refpoints))));
> >+ if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
> >+ add_str(hypertas, "hcall-multi-tce");
> >+ }
> >+ qdt_setprop(rtas, "ibm,hypertas-functions",
> >+ hypertas->str, hypertas->len);
> >+ g_string_free(hypertas, TRUE);
> >+ qdt_setprop(rtas, "qemu,hypertas-functions",
> >+ qemu_hypertas->str, qemu_hypertas->len);
> >+ g_string_free(qemu_hypertas, TRUE);
> >
> >- _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
> >- _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate",
> >- RTAS_EVENT_SCAN_RATE)));
> >+ qdt_setprop_cells(rtas, "ibm,associativity-reference-points", 0x4, 0x4);
> >
> >- if (msi_nonbroken) {
> >- _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0)));
> >- }
> >+ qdt_setprop_cells(rtas, "rtas-error-log-max", RTAS_ERROR_LOG_MAX);
> >+ qdt_setprop_cells(rtas, "rtas-event-scan-rate", RTAS_EVENT_SCAN_RATE);
> >
> >- /*
> >- * According to PAPR, rtas ibm,os-term does not guarantee a return
> >- * back to the guest cpu.
> >- *
> >- * While an additional ibm,extended-os-term property indicates that
> >- * rtas call return will always occur. Set this property.
> >- */
> >- _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
> >+ if (msi_nonbroken) {
> >+ qdt_setprop_empty(rtas, "ibm,change-msix-capable");
> >+ }
> >+
> >+ /*
> >+ * According to PAPR, rtas ibm,os-term does not guarantee a
> >+ * return back to the guest cpu.
> >+ *
> >+ * While an additional ibm,extended-os-term property indicates
> >+ * that rtas call return will always occur. Set this property.
> >+ */
> >+ qdt_setprop_empty(rtas, "ibm,extended-os-term");
> >+ }
> >
> >- _FDT((fdt_end_node(fdt)));
> >+ /* /interrupt controller */
> >+ {
> >+ QDTNode *xics = qdt_add_subnode(root, "interrupt-controller");
> >
> >- /* interrupt controller */
> >- _FDT((fdt_begin_node(fdt, "interrupt-controller")));
> >+ qdt_setprop_string(xics, "device_type",
> >+ "PowerPC-External-Interrupt-Presentation");
> >+ qdt_setprop_string(xics, "compatible", "IBM,ppc-xicp");
> >+ qdt_setprop_empty(xics, "interrupt-controller");
> >+ qdt_setprop_cells(xics, "ibm,interrupt-server-ranges", 0, max_cpus);
> >+ qdt_setprop_cells(xics, "#interrupt-cells", 2);
> >+ qdt_set_phandle(xics, PHANDLE_XICP);
> >+ }
> >
> >- _FDT((fdt_property_string(fdt, "device_type",
> >- "PowerPC-External-Interrupt-Presentation")));
> >- _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp")));
> >- _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> >- _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges",
> >- interrupt_server_ranges_prop,
> >- sizeof(interrupt_server_ranges_prop))));
> >- _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> >- _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP)));
> >- _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP)));
> >+ /* /vdevice */
> >+ {
> >+ QDTNode *vdevice = qdt_add_subnode(root, "vdevice");
> >
> >- _FDT((fdt_end_node(fdt)));
> >+ qdt_setprop_string(vdevice, "device_type", "vdevice");
> >+ qdt_setprop_string(vdevice, "compatible", "IBM,vdevice");
> >+ qdt_setprop_cells(vdevice, "#address-cells", 0x1);
> >+ qdt_setprop_cells(vdevice, "#size-cells", 0x0);
> >+ qdt_setprop_cells(vdevice, "#interrupt-cells", 0x2);
> >+ qdt_setprop_empty(vdevice, "interrupt-controller");
> >+ }
> >
> >- /* vdevice */
> >- _FDT((fdt_begin_node(fdt, "vdevice")));
> >
> >- _FDT((fdt_property_string(fdt, "device_type", "vdevice")));
> >- _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice")));
> >- _FDT((fdt_property_cell(fdt, "#address-cells", 0x1)));
> >- _FDT((fdt_property_cell(fdt, "#size-cells", 0x0)));
> >- _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2)));
> >- _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> >+ /* /event-sources */
> >+ {
> >+ QDTNode *event_sources = qdt_add_subnode(root, "event-sources");
> >+ QDTNode *epow;
> >
> >- _FDT((fdt_end_node(fdt)));
> >+ qdt_setprop_empty(event_sources, "interrupt-controller");
> >+ qdt_setprop_cells(event_sources, "#interrupt-cells", 2);
> >+ qdt_setprop_cells(event_sources, "interrupt-ranges",
> >+ spapr->check_exception_irq, 1);
> >
> >- /* event-sources */
> >- spapr_events_fdt_skel(fdt, spapr->check_exception_irq);
> >+ epow = qdt_add_subnode(event_sources, "epow-events");
> >+ qdt_setprop_cells(epow, "interrupts", spapr->check_exception_irq, 0);
> >+ }
> >
> >- /* /hypervisor node */
> >+ /* /hypervisor */
> > if (kvm_enabled()) {
> >- uint8_t hypercall[16];
> >+ QDTNode *hypervisor = qdt_add_subnode(root, "hypervisor");
> >
> > /* indicate KVM hypercall interface */
> >- _FDT((fdt_begin_node(fdt, "hypervisor")));
> >- _FDT((fdt_property_string(fdt, "compatible", "linux,kvm")));
> >+ qdt_setprop_string(hypervisor, "compatible", "linux,kvm");
> > if (kvmppc_has_cap_fixup_hcalls()) {
> >+ uint8_t hypercall[16];
> > /*
> > * Older KVM versions with older guest kernels were broken with the
> > * magic page, don't allow the guest to map it.
> > */
> > if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
> > sizeof(hypercall))) {
> >- _FDT((fdt_property(fdt, "hcall-instructions", hypercall,
> >- sizeof(hypercall))));
> >+ qdt_setprop(hypervisor, "hcall-instructions",
> >+ hypercall, sizeof(hypercall));
> > }
> > }
> >- _FDT((fdt_end_node(fdt)));
> > }
> >
> >- _FDT((fdt_end_node(fdt))); /* close root node */
> >- _FDT((fdt_finish(fdt)));
> >+ fdt = qdt_flatten(root, FDT_MAX_SIZE, &error_fatal);
> >
> > /* open out the base tree into a temp buffer for the final tweaks */
> > _FDT((fdt_open_into(fdt, fdt, FDT_MAX_SIZE)));
> >diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
> >index 269ab7e..cce219f 100644
> >--- a/hw/ppc/spapr_events.c
> >+++ b/hw/ppc/spapr_events.c
> >@@ -220,25 +220,6 @@ struct hp_log_full {
> > } \
> > } while (0)
> >
> >-void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
> >-{
> >- uint32_t irq_ranges[] = {cpu_to_be32(check_exception_irq), cpu_to_be32(1)};
> >- uint32_t interrupts[] = {cpu_to_be32(check_exception_irq), 0};
> >-
> >- _FDT((fdt_begin_node(fdt, "event-sources")));
> >-
> >- _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0)));
> >- _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2)));
> >- _FDT((fdt_property(fdt, "interrupt-ranges",
> >- irq_ranges, sizeof(irq_ranges))));
> >-
> >- _FDT((fdt_begin_node(fdt, "epow-events")));
> >- _FDT((fdt_property(fdt, "interrupts", interrupts, sizeof(interrupts))));
> >- _FDT((fdt_end_node(fdt)));
> >-
> >- _FDT((fdt_end_node(fdt)));
> >-}
> >-
> > static void rtas_event_log_queue(int log_type, void *data, bool exception)
> > {
> > sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
> >diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> >index ebad34f..40d3724 100644
> >--- a/include/hw/ppc/spapr.h
> >+++ b/include/hw/ppc/spapr.h
> >@@ -560,7 +560,6 @@ struct sPAPREventLogEntry {
> > };
> >
> > void spapr_events_init(sPAPRMachineState *sm);
> >-void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
> > int spapr_h_cas_compose_response(sPAPRMachineState *sm,
> > target_ulong addr, target_ulong size,
> > bool cpu_update, bool memory_update);
> >
>
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 11/11] pseries: Remove unused callbacks from sPAPR VIO bus state
2016-04-21 5:31 ` Alexey Kardashevskiy
@ 2016-04-27 6:22 ` David Gibson
0 siblings, 0 replies; 44+ messages in thread
From: David Gibson @ 2016-04-27 6:22 UTC (permalink / raw)
To: Alexey Kardashevskiy; +Cc: agraf, crosthwaite.peter, qemu-ppc, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 749 bytes --]
On Thu, Apr 21, 2016 at 03:31:33PM +1000, Alexey Kardashevskiy wrote:
> On 04/20/2016 12:33 PM, David Gibson wrote:
> >The VIOsPAPRBus structure has some callback pointers in it which aren't
> >used anywhere in the code. It's not clear exactly why they were there in
> >the first place, but they certainly have no function now.
>
> It is clear - incorrect QOM'fication in 3954d33ab7f82f5a5 when parts of
> VIOsPAPRDeviceInfo became parts of VIOsPAPRBus, you can adjust the commit
> log :)
Thanks for the research, I'll update accordingly.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-27 6:02 ` David Gibson
@ 2016-04-27 6:43 ` Markus Armbruster
2016-04-27 7:06 ` Thomas Huth
0 siblings, 1 reply; 44+ messages in thread
From: Markus Armbruster @ 2016-04-27 6:43 UTC (permalink / raw)
To: David Gibson
Cc: Thomas Huth, aik, qemu-devel, qemu-ppc, agraf, crosthwaite.peter
David Gibson <david@gibson.dropbear.id.au> writes:
> On Tue, Apr 26, 2016 at 01:00:06PM +0200, Thomas Huth wrote:
>> On 20.04.2016 04:33, David Gibson wrote:
>> ...
>> > This patch introduces a new utility library "qdt" for runtime
>> > manipulation of device trees. The intention is that machine type code
>> > can use these routines to construct the device tree conveniently,
>> > using a pointer-based representation doesn't have the limitations
>> > above. They can then use qdt_flatten() to convert the completed tree
>> > to fdt format as a single O(n) operation to pass to the guest.
>>
>> Good idea, the FDT format itself is really not very well suited for
>> dynamic manipulations...
>>
>> ...
>> > diff --git a/util/qdt.c b/util/qdt.c
>> > new file mode 100644
>> > index 0000000..e3a449a
>> > --- /dev/null
>> > +++ b/util/qdt.c
>> > @@ -0,0 +1,262 @@
>> > +/*
>> > + * Functions for manipulating IEEE1275 (Open Firmware) style device
>> > + * trees.
>>
>> What does QDT stand for? Maybe add that in the description here.
>
> "QEMU Device Tree" I guess? Really I was just looking for something
> similar but not the same as fdt, and short.
>
>> > + * Copyright David Gibson, Red Hat Inc. 2016
>> > + *
>> > + * This work is licensed unter the GNU GPL version 2 or (at your
>> > + * option) any later version.
>> > + */
>> > +
>> > +#include <libfdt.h>
>> > +#include <stdbool.h>
>> > +
>> > +#include "qemu/osdep.h"
>> > +#include "qapi/error.h"
>> > +#include "qemu/qdt.h"
>> > +#include "qemu/error-report.h"
>> > +
>> > +/*
>> > + * Node functions
>> > + */
>> > +
>> > +QDTNode *qdt_new_node(const gchar *name)
>> > +{
>> > + QDTNode *node = g_new0(QDTNode, 1);
>> > +
>> > + g_assert(!strchr(name, '/'));
>> > +
>> > + node->name = g_strdup(name);
>> > + QTAILQ_INIT(&node->properties);
>> > + QTAILQ_INIT(&node->children);
>> > +
>> > + return node;
>> > +}
>> > +
>> > +static QDTNode *get_subnode(QDTNode *parent, const gchar *name, size_t namelen)
>> > +{
>> > + QDTNode *child;
>> > +
>> > + g_assert(!memchr(name, '/', namelen));
>> > +
>> > + QTAILQ_FOREACH(child, &parent->children, sibling) {
>> > + if ((strlen(child->name) == namelen)
>> > + && (memcmp(child->name, name, namelen) == 0)) {
>>
>> Too many parenthesis for my taste ;-)
Mine too.
>> > + return child;
>> > + }
>> > + }
>> > +
>> > + return NULL;
>> > +}
>> > +
>> > +QDTNode *qdt_get_node_relative(QDTNode *node, const gchar *path)
>> > +{
>> > + const gchar *slash;
>> > + gsize seglen;
>> > +
>> > + do {
>> > + slash = strchr(path, '/');
>> > + seglen = slash ? slash - path : strlen(path);
>> > +
>> > + node = get_subnode(node, path, seglen);
>> > + path += seglen + 1;
>> > + } while (node && slash);
>> > +
>> > + return node;
>> > +}
>> > +
>> > +QDTNode *qdt_get_node(QDTNode *root, const gchar *path)
>> > +{
>> > + g_assert(!root->parent);
>> > + g_assert(path[0] == '/');
>> > + return qdt_get_node_relative(root, path + 1);
>> > +}
>> > +
>> > +QDTNode *qdt_add_subnode(QDTNode *parent, const gchar *name)
>> > +{
>> > + QDTNode *new = qdt_new_node(name);
>> > +
>> > + new->parent = parent;
>> > + QTAILQ_INSERT_TAIL(&parent->children, new, sibling);
>> > + return new;
>> > +}
>>
>> In case somebody ever tries to compile this with a C++ compiler ... it's
>> maybe better avoid using "new" as name for a variable.
>
> Good point, will change.
My answer to "what if somebody tries to compile this code with a
compiler for a different language" is "hope it won't compile then, for
the innocents' sake".
>> > +/*
>> > + * Property functions
>> > + */
>> > +
>> > +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
>> > +{
>> > + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
>> > +
>> > + prop->name = g_strdup(name);
>> > + prop->len = len;
>> > + memcpy(prop->val, val, len);
>> > + return prop;
>> > +}
>> > +
>> > +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
>>
>> Underscore at the end looks somewhat strange ... can't you simply drop that?
>
> Well.. the idea was that the _ versions are the "internal" ones,
> whereas external users will generally use the non-underscore version
I've seen that convention used before. It's fine with me.
> (in this case the only difference is that the external one returns a
> const pointer).
>
> I don't particularly like that convention, so feel free to suggest
> something better.
Consider getprop_internal() if the length isn't bothersome. It is when
the name is used all over the place.
do_getprop() would be shorter. I don't like do_verb names myself.
[...]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-27 6:43 ` Markus Armbruster
@ 2016-04-27 7:06 ` Thomas Huth
2016-04-27 7:28 ` Markus Armbruster
0 siblings, 1 reply; 44+ messages in thread
From: Thomas Huth @ 2016-04-27 7:06 UTC (permalink / raw)
To: Markus Armbruster, David Gibson
Cc: crosthwaite.peter, aik, qemu-devel, agraf, qemu-ppc
On 27.04.2016 08:43, Markus Armbruster wrote:
> David Gibson <david@gibson.dropbear.id.au> writes:
>
>> On Tue, Apr 26, 2016 at 01:00:06PM +0200, Thomas Huth wrote:
>>> On 20.04.2016 04:33, David Gibson wrote:
[...]
>>>> +/*
>>>> + * Property functions
>>>> + */
>>>> +
>>>> +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
>>>> +{
>>>> + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
>>>> +
>>>> + prop->name = g_strdup(name);
>>>> + prop->len = len;
>>>> + memcpy(prop->val, val, len);
>>>> + return prop;
>>>> +}
>>>> +
>>>> +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
>>>
>>> Underscore at the end looks somewhat strange ... can't you simply drop that?
>>
>> Well.. the idea was that the _ versions are the "internal" ones,
>> whereas external users will generally use the non-underscore version
>
> I've seen that convention used before. It's fine with me.
Can't remember to have seen that convention before ... I know that some
people use the underscore at the beginning to mark an internal function,
but at the end?
So if you really want to use the underscore, what about putting it at
the beginning instead?
>> (in this case the only difference is that the external one returns a
>> const pointer).
>>
>> I don't particularly like that convention, so feel free to suggest
>> something better.
>
> Consider getprop_internal() if the length isn't bothersome. It is when
> the name is used all over the place.
>
> do_getprop() would be shorter. I don't like do_verb names myself.
Both ideas also sound fine to me.
Thomas
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-27 7:06 ` Thomas Huth
@ 2016-04-27 7:28 ` Markus Armbruster
2016-04-27 7:56 ` Thomas Huth
2016-04-27 23:49 ` David Gibson
0 siblings, 2 replies; 44+ messages in thread
From: Markus Armbruster @ 2016-04-27 7:28 UTC (permalink / raw)
To: Thomas Huth
Cc: David Gibson, aik, agraf, qemu-ppc, qemu-devel, crosthwaite.peter
Thomas Huth <thuth@redhat.com> writes:
> On 27.04.2016 08:43, Markus Armbruster wrote:
>> David Gibson <david@gibson.dropbear.id.au> writes:
>>
>>> On Tue, Apr 26, 2016 at 01:00:06PM +0200, Thomas Huth wrote:
>>>> On 20.04.2016 04:33, David Gibson wrote:
> [...]
>>>>> +/*
>>>>> + * Property functions
>>>>> + */
>>>>> +
>>>>> +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
>>>>> +{
>>>>> + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
>>>>> +
>>>>> + prop->name = g_strdup(name);
>>>>> + prop->len = len;
>>>>> + memcpy(prop->val, val, len);
>>>>> + return prop;
>>>>> +}
>>>>> +
>>>>> +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
>>>>
>>>> Underscore at the end looks somewhat strange ... can't you simply drop that?
>>>
>>> Well.. the idea was that the _ versions are the "internal" ones,
>>> whereas external users will generally use the non-underscore version
>>
>> I've seen that convention used before. It's fine with me.
>
> Can't remember to have seen that convention before ... I know that some
> people use the underscore at the beginning to mark an internal function,
> but at the end?
> So if you really want to use the underscore, what about putting it at
> the beginning instead?
C99 7.1.3 Reserved identifiers:
-- All identifiers that begin with an underscore are
always reserved for use as identifiers with file scope
in both the ordinary and tag name spaces.
[...]
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-27 7:28 ` Markus Armbruster
@ 2016-04-27 7:56 ` Thomas Huth
2016-04-27 8:36 ` Markus Armbruster
2016-04-27 23:49 ` David Gibson
1 sibling, 1 reply; 44+ messages in thread
From: Thomas Huth @ 2016-04-27 7:56 UTC (permalink / raw)
To: Markus Armbruster
Cc: David Gibson, aik, agraf, qemu-ppc, qemu-devel, crosthwaite.peter
On 27.04.2016 09:28, Markus Armbruster wrote:
> Thomas Huth <thuth@redhat.com> writes:
>
>> On 27.04.2016 08:43, Markus Armbruster wrote:
>>> David Gibson <david@gibson.dropbear.id.au> writes:
>>>
>>>> On Tue, Apr 26, 2016 at 01:00:06PM +0200, Thomas Huth wrote:
>>>>> On 20.04.2016 04:33, David Gibson wrote:
>> [...]
>>>>>> +/*
>>>>>> + * Property functions
>>>>>> + */
>>>>>> +
>>>>>> +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
>>>>>> +{
>>>>>> + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
>>>>>> +
>>>>>> + prop->name = g_strdup(name);
>>>>>> + prop->len = len;
>>>>>> + memcpy(prop->val, val, len);
>>>>>> + return prop;
>>>>>> +}
>>>>>> +
>>>>>> +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
>>>>>
>>>>> Underscore at the end looks somewhat strange ... can't you simply drop that?
>>>>
>>>> Well.. the idea was that the _ versions are the "internal" ones,
>>>> whereas external users will generally use the non-underscore version
>>>
>>> I've seen that convention used before. It's fine with me.
>>
>> Can't remember to have seen that convention before ... I know that some
>> people use the underscore at the beginning to mark an internal function,
>> but at the end?
>> So if you really want to use the underscore, what about putting it at
>> the beginning instead?
>
> C99 7.1.3 Reserved identifiers:
>
> -- All identifiers that begin with an underscore are
> always reserved for use as identifiers with file scope
> in both the ordinary and tag name spaces.
Oh, I always thought that underscore + lowercase letter would still be
OK for local variables and functions, since for example
http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html says:
"In addition to the names documented in this manual, reserved names
include all external identifiers (global functions and variables) that
begin with an underscore (‘_’) and all identifiers regardless of use
that begin with either two underscores or an underscore followed by a
capital letter are reserved names"
... that sounds like the underscore rule only applies to global
functions and variables (and to those where the underscore is followed
by a capital letter or another underscore).
But if I've got your quote right, a leading underscore _always_
indicates a reserved name for functions and variables, no matter whether
they are local or global... Well, you learn something new
every day :-)
Thomas
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-27 7:56 ` Thomas Huth
@ 2016-04-27 8:36 ` Markus Armbruster
0 siblings, 0 replies; 44+ messages in thread
From: Markus Armbruster @ 2016-04-27 8:36 UTC (permalink / raw)
To: Thomas Huth
Cc: crosthwaite.peter, aik, qemu-devel, agraf, qemu-ppc, David Gibson
Thomas Huth <thuth@redhat.com> writes:
> On 27.04.2016 09:28, Markus Armbruster wrote:
>> Thomas Huth <thuth@redhat.com> writes:
>>
>>> On 27.04.2016 08:43, Markus Armbruster wrote:
>>>> David Gibson <david@gibson.dropbear.id.au> writes:
>>>>
>>>>> On Tue, Apr 26, 2016 at 01:00:06PM +0200, Thomas Huth wrote:
>>>>>> On 20.04.2016 04:33, David Gibson wrote:
>>> [...]
>>>>>>> +/*
>>>>>>> + * Property functions
>>>>>>> + */
>>>>>>> +
>>>>>>> +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
>>>>>>> +{
>>>>>>> + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
>>>>>>> +
>>>>>>> + prop->name = g_strdup(name);
>>>>>>> + prop->len = len;
>>>>>>> + memcpy(prop->val, val, len);
>>>>>>> + return prop;
>>>>>>> +}
>>>>>>> +
>>>>>>> +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
>>>>>>
>>>>>> Underscore at the end looks somewhat strange ... can't you simply drop that?
>>>>>
>>>>> Well.. the idea was that the _ versions are the "internal" ones,
>>>>> whereas external users will generally use the non-underscore version
>>>>
>>>> I've seen that convention used before. It's fine with me.
>>>
>>> Can't remember to have seen that convention before ... I know that some
>>> people use the underscore at the beginning to mark an internal function,
>>> but at the end?
>>> So if you really want to use the underscore, what about putting it at
>>> the beginning instead?
>>
>> C99 7.1.3 Reserved identifiers:
Additional context:
-- All identifiers that begin with an underscore and
either an uppercase letter or another underscore are
always reserved for any use.
>> -- All identifiers that begin with an underscore are
>> always reserved for use as identifiers with file scope
>> in both the ordinary and tag name spaces.
>
> Oh, I always thought that underscore + lowercase letter would still be
> OK for local variables and functions, since for example
> http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html says:
>
> "In addition to the names documented in this manual, reserved names
> include all external identifiers (global functions and variables) that
> begin with an underscore (‘_’) and all identifiers regardless of use
> that begin with either two underscores or an underscore followed by a
> capital letter are reserved names"
>
> ... that sounds like the underscore rule only applies to global
> functions and variables (and to those where the underscore is followed
> by a capital letter or another underscore).
>
> But if I've got your quote right, a leading underscore _always_
> indicates a reserved name for functions and variables, no matter whether
> they are local or global... Well, you learn something new
> every day :-)
Almost. Compare the two clauses carefully: the first one reserves "for
any use", the second one "for use as identifiers with file scope in both
the ordinary and tag name spaces." The difference is the quantifiers
"file scope" and "ordinary and tag name spaces".
The scopes are function, file, block, function prototype (the parameter
list). See 6.2.1 Scopes of identifiers.
The name spaces are label, struct/union/enum tag, each struct or union
for its members, and ordinary. See 6.2.3 Name spaces of identifiers.
Thus, the second clause doesn't apply to labels, struct/union members,
and local variables including arguments.
However, if you need to quote three sections of the standard to convince
yourself that an identifier is okay, perhaps you should pick another one
:)
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 06/11] pseries: Consolidate RTAS loading
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 06/11] pseries: Consolidate RTAS loading David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
@ 2016-04-27 9:12 ` Thomas Huth
1 sibling, 0 replies; 44+ messages in thread
From: Thomas Huth @ 2016-04-27 9:12 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel
On 20.04.2016 04:33, David Gibson wrote:
> At each system reset, the pseries machine needs to load RTAS, the run
> time portion of the guest firmware, into the VM. This means copying
> the actual RTAS code into guest memory, and also updating the device
> tree so that the guest OS and boot firmware can locate it.
>
> For historical reasons the copy and update to the device tree were in
> different parts of the code. This cleanup brings them both together in
> an spapr_load_rtas() function.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Thomas Huth <thuth@redhat.com>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries David Gibson
2016-04-21 5:14 ` Alexey Kardashevskiy
@ 2016-04-27 9:19 ` Thomas Huth
1 sibling, 0 replies; 44+ messages in thread
From: Thomas Huth @ 2016-04-27 9:19 UTC (permalink / raw)
To: David Gibson, agraf, crosthwaite.peter; +Cc: aik, qemu-ppc, qemu-devel
On 20.04.2016 04:33, David Gibson wrote:
> The flattened device tree passed to pseries guests contains a list of
> reserved memory areas. Currently we construct this list early in
> spapr_build_fdt() as we sequentially write out the fdt.
>
> This will be inconvenient for upcoming cleanups, so this patch moves
> the reserve map changes to the end of fdt construction. This changes
> fdt_add_reservemap_entry() calls - which work when writing the fdt
> sequentially to fdt_add_mem_rsv() calls used when altering the fdt in
> random access mode.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> hw/ppc/spapr.c | 17 +++++++++--------
> 1 file changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 5356f4d..aef44a2 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -733,14 +733,6 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> fdt = g_malloc0(FDT_MAX_SIZE);
> _FDT((fdt_create(fdt, FDT_MAX_SIZE)));
>
> - if (spapr->kernel_size) {
> - _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR,
> - spapr->kernel_size)));
> - }
> - if (spapr->initrd_size) {
> - _FDT((fdt_add_reservemap_entry(fdt, spapr->initrd_base,
> - spapr->initrd_size)));
> - }
> _FDT((fdt_finish_reservemap(fdt)));
>
> /* Root node */
> @@ -976,6 +968,15 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
> }
>
> g_free(bootlist);
> +
> + /* Build memory reserve map */
> + if (spapr->kernel_size) {
> + _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
> + }
> + if (spapr->initrd_size) {
> + _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size)));
> + }
> +
> return fdt;
> }
Reviewed-by: Thomas Huth <thuth@redhat.com>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code
2016-04-27 7:28 ` Markus Armbruster
2016-04-27 7:56 ` Thomas Huth
@ 2016-04-27 23:49 ` David Gibson
1 sibling, 0 replies; 44+ messages in thread
From: David Gibson @ 2016-04-27 23:49 UTC (permalink / raw)
To: Markus Armbruster
Cc: Thomas Huth, aik, agraf, qemu-ppc, qemu-devel, crosthwaite.peter
[-- Attachment #1: Type: text/plain, Size: 2128 bytes --]
On Wed, Apr 27, 2016 at 09:28:57AM +0200, Markus Armbruster wrote:
> Thomas Huth <thuth@redhat.com> writes:
>
> > On 27.04.2016 08:43, Markus Armbruster wrote:
> >> David Gibson <david@gibson.dropbear.id.au> writes:
> >>
> >>> On Tue, Apr 26, 2016 at 01:00:06PM +0200, Thomas Huth wrote:
> >>>> On 20.04.2016 04:33, David Gibson wrote:
> > [...]
> >>>>> +/*
> >>>>> + * Property functions
> >>>>> + */
> >>>>> +
> >>>>> +QDTProperty *qdt_new_property(const gchar *name, gconstpointer val, gsize len)
> >>>>> +{
> >>>>> + QDTProperty *prop = g_malloc0(sizeof(*prop) + len);
> >>>>> +
> >>>>> + prop->name = g_strdup(name);
> >>>>> + prop->len = len;
> >>>>> + memcpy(prop->val, val, len);
> >>>>> + return prop;
> >>>>> +}
> >>>>> +
> >>>>> +static QDTProperty *getprop_(const QDTNode *node, const gchar *name)
> >>>>
> >>>> Underscore at the end looks somewhat strange ... can't you simply drop that?
> >>>
> >>> Well.. the idea was that the _ versions are the "internal" ones,
> >>> whereas external users will generally use the non-underscore version
> >>
> >> I've seen that convention used before. It's fine with me.
> >
> > Can't remember to have seen that convention before ... I know that some
> > people use the underscore at the beginning to mark an internal function,
> > but at the end?
> > So if you really want to use the underscore, what about putting it at
> > the beginning instead?
>
> C99 7.1.3 Reserved identifiers:
>
> -- All identifiers that begin with an underscore are
> always reserved for use as identifiers with file scope
> in both the ordinary and tag name spaces.
Right. The kernel uses the _ prefix convention, but it can kind of
get away with it, because it doesn't use the standard library. For
things in userspace, _ prefixed identifiers are reserved, hence using
the _ suffix instead.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply [flat|nested] 44+ messages in thread
end of thread, other threads:[~2016-04-28 0:03 UTC | newest]
Thread overview: 44+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-04-20 2:33 [Qemu-devel] [RFC for-2.7 00/11] A new infrastructure for guest device trees David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 01/11] qdt: IEEE1275-style device tree utility code David Gibson
2016-04-21 6:01 ` Alexey Kardashevskiy
2016-04-22 4:15 ` David Gibson
2016-04-26 11:00 ` Thomas Huth
2016-04-27 6:02 ` David Gibson
2016-04-27 6:43 ` Markus Armbruster
2016-04-27 7:06 ` Thomas Huth
2016-04-27 7:28 ` Markus Armbruster
2016-04-27 7:56 ` Thomas Huth
2016-04-27 8:36 ` Markus Armbruster
2016-04-27 23:49 ` David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 02/11] pseries: Split device tree construction from device tree load David Gibson
2016-04-20 18:15 ` Thomas Huth
2016-04-21 5:31 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 03/11] pseries: Remove rtas_addr and fdt_addr fields from machinestate David Gibson
2016-04-20 18:19 ` Thomas Huth
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 04/11] pseries: Make spapr_create_fdt_skel() get information from machine state David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-26 17:41 ` Thomas Huth
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 05/11] pseries: Build device tree only at reset time David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-26 18:13 ` Thomas Huth
2016-04-27 6:07 ` David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 06/11] pseries: Consolidate RTAS loading David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-27 9:12 ` Thomas Huth
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 07/11] pseries: Move adding of fdt reserve map entries David Gibson
2016-04-21 5:14 ` Alexey Kardashevskiy
2016-04-21 5:52 ` David Gibson
2016-04-21 6:03 ` Alexey Kardashevskiy
2016-04-22 4:22 ` David Gibson
2016-04-27 9:19 ` Thomas Huth
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 08/11] pseries: Start using qdt library for building device tree David Gibson
2016-04-21 4:04 ` Alexey Kardashevskiy
2016-04-27 6:13 ` David Gibson
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 09/11] pseries: Consolidate construction of /chosen device tree node David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 10/11] pseries: Consolidate construction of /rtas " David Gibson
2016-04-21 5:32 ` Alexey Kardashevskiy
2016-04-20 2:33 ` [Qemu-devel] [RFC for-2.7 11/11] pseries: Remove unused callbacks from sPAPR VIO bus state David Gibson
2016-04-21 5:31 ` Alexey Kardashevskiy
2016-04-27 6:22 ` David Gibson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).