[SLOF] [PATCH slof] fdt: Pass the resulting device tree to QEMU
Alexey Kardashevskiy
aik at ozlabs.ru
Fri Sep 29 19:07:29 AEST 2017
This creates flatten device tree and passes it to QEMU via a custom
hypercall right before jumping to RTAS.
On a machine with 256 CPUs and 256 virtual Intel E1000 devices the blob
is 360KB (356KB structs and 4KB of strings), building such a tree takes
2.8s on a POWER8 box. A simple tree with 1 CPU and a couple of devices
takes 43ms and creates 16KB blob.
Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
---
I tested the blob by storing it from QEMU to a file (RFC patch is
coming next) and decompiling it; this produces error which I do not really
understand as the name of the root is an empty string (literaly:
00 00 00 01 00 00 00 00) and yet this error:
aik at fstn1-p1:~$ dtc -f -I dtb -O dts -o dbg.dts dbg.dtb
ERROR (name_properties): "name" property in / is incorrect ("/" instead of base node name)
Warning: Input tree has errors, output forced
---
lib/libhvcall/libhvcall.h | 1 +
board-qemu/slof/fdt.fs | 224 +++++++++++++++++++++++++++++++++++++++++++++-
board-qemu/slof/rtas.fs | 4 +
lib/libhvcall/hvcall.code | 5 ++
lib/libhvcall/hvcall.in | 1 +
5 files changed, 234 insertions(+), 1 deletion(-)
diff --git a/lib/libhvcall/libhvcall.h b/lib/libhvcall/libhvcall.h
index 5776a2b..1c2d31b 100644
--- a/lib/libhvcall/libhvcall.h
+++ b/lib/libhvcall/libhvcall.h
@@ -26,6 +26,7 @@
#define KVMPPC_H_CAS (KVMPPC_HCALL_BASE + 0x2)
#define KVMPPC_H_RTAS_UPDATE (KVMPPC_HCALL_BASE + 0x3)
#define KVMPPC_H_UPDATE_PHANDLE (KVMPPC_HCALL_BASE + 0x4)
+#define KVMPPC_H_UPDATE_DT (KVMPPC_HCALL_BASE + 0x5)
#ifndef __ASSEMBLY__
diff --git a/board-qemu/slof/fdt.fs b/board-qemu/slof/fdt.fs
index a24e344..b99746a 100644
--- a/board-qemu/slof/fdt.fs
+++ b/board-qemu/slof/fdt.fs
@@ -27,7 +27,7 @@ struct
4 field >fdth_boot_cpu
4 field >fdth_string_size
4 field >fdth_struct_size
-drop
+constant /fdth
h# d00dfeed constant OF_DT_HEADER
h# 1 constant OF_DT_BEGIN_NODE
@@ -449,4 +449,226 @@ r> drop
fdt-cas-fix?
;
+VARIABLE fdt-struct
+VARIABLE fdt-struct-cur
+VARIABLE fdt-strings
+VARIABLE fdt-strings-cur
+VARIABLE fdt-strings-reused
+VARIABLE fdt-ms
+
+: fdt-struct-add ( bytes len nullterminate -- )
+ >r
+ dup >r ( bytes len r: nullterminate len )
+ fdt-struct-cur @ swap ( bytes cur len r: nullterminate len )
+ move
+ fdt-struct-cur @ ( cur r: nullterminate len )
+ r> + ( cur r: nullterminate )
+ r> IF
+ 0 over c!
+ 1+
+ THEN
+ 3 + -4 and
+ fdt-struct-cur !
+;
+
+: fdt-add-long ( token -- )
+ fdt-struct-cur @
+ l!
+ fdt-struct-cur @
+ 4 +
+ fdt-struct-cur !
+;
+
+: skip-to-next ( cur -- cur )
+ BEGIN
+ dup c@
+ WHILE
+ 1+
+ REPEAT
+ 4 + -4 and
+;
+
+: string-equal ( name namelen str -- true | false )
+ 3dup swap comp 0 <> IF
+ 3drop
+ false
+ EXIT
+ THEN
+ + c@ 0 = nip
+
+ dup IF
+ fdt-strings-reused @ 1+ fdt-strings-reused !
+ THEN
+;
+
+: fdt-get-string ( name namelen -- nameoff )
+ \ lookup
+ fdt-strings @
+ BEGIN
+ dup fdt-strings-cur @
+ = not
+ WHILE
+ 3dup string-equal IF
+ \ found it, no need to add new one
+ fdt-strings @ -
+ -rot
+ 2drop
+ EXIT
+ THEN
+ skip-to-next
+ REPEAT
+ drop
+
+ \ store cur offset
+ fdt-strings-cur @ fdt-strings @ - >r
+
+ \ store len
+ dup >r
+
+ \ copy string
+ fdt-strings-cur @ swap ( name cur namelen )
+ move
+
+ \ increment cur and null terminate
+ fdt-strings-cur @
+ r> +
+ 0 over c!
+ 4 + -4 and
+ fdt-strings-cur !
+
+ \ return offset
+ r>
+;
+
+: fdt-begin-node ( name namelen -- )
+ OF_DT_BEGIN_NODE fdt-add-long
+ 2dup 1 = swap c@ 2F = and \ is it "/"?
+ IF
+ 2drop s" " \ dtc is still unhappy though
+ THEN
+ true fdt-struct-add
+;
+
+: fdt-end-node ( -- )
+ OF_DT_END_NODE fdt-add-long
+;
+
+: fdt-prop ( prop len name namelen -- )
+ OF_DT_PROP fdt-add-long
+
+ \ get string offset
+ fdt-get-string ( prop len nameoff )
+
+ \ store len and nameoff
+ over fdt-add-long
+ fdt-add-long ( prop len )
+
+ \ now add the bytes
+ false fdt-struct-add
+;
+
+: fdt-end ( -- )
+ OF_DT_END fdt-add-long
+;
+
+: fdt-properties ( phandle -- )
+ >r
+ s" "
+ BEGIN
+ r@ next-property
+ WHILE
+ 2dup
+ 2dup r@ get-property
+ not IF
+ 2swap fdt-prop
+ THEN
+ REPEAT
+ r>
+ drop
+;
+
+: fdt-flatten-node ( node -- )
+\ fdt-debug IF dup node>path type cr THEN
+ dup node>qname fdt-begin-node
+ dup fdt-properties
+ child
+ BEGIN
+ dup
+ WHILE
+ dup recurse
+ peer
+ REPEAT
+ drop
+ fdt-end-node
+;
+
+: fdt-flatten-tree ( root -- tree )
+ 200000 alloc-mem dup fdt-struct-cur ! fdt-struct !
+ 10000 alloc-mem dup fdt-strings-cur ! fdt-strings !
+ 0 fdt-strings-reused !
+ milliseconds fdt-ms !
+
+ fdt-flatten-node
+ fdt-end
+
+ fdt-struct-cur @ fdt-struct @ -
+ fdt-strings-cur @ fdt-strings @ -
+ fdt-debug IF
+ 2dup
+ ." Strings=" .d cr
+ ." Struct=" .d cr
+ ." Reused strings=" fdt-strings-reused @ .d cr
+ milliseconds fdt-ms @ -
+ ." Took " .d ." ms" cr
+ THEN
+
+ 2dup + /fdth +
+ 10 + \ reserved block
+ dup
+ fdt-debug IF
+ dup ." FDT flat size=" .d cr
+ THEN
+ alloc-mem ( struct-len strings-len totallen fdt )
+ >r ( struct-len strings-len totallen r: fdt )
+
+ \ write header
+ OF_DT_HEADER r@ >fdth_magic l!
+ dup r@ >fdth_tsize l!
+ /fdth 10 + 2 pick + r@ >fdth_struct_off l!
+ /fdth 10 + r@ >fdth_string_off l!
+ /fdth r@ >fdth_rsvmap_off l!
+ 17 r@ >fdth_version l!
+ 17 r@ >fdth_compat_vers l!
+ 0 r@ >fdth_boot_cpu l!
+ over r@ >fdth_string_size l!
+ 2 pick r@ >fdth_struct_size l!
+
+ drop
+ r@ /fdth + ( struct-len strings-len curfdt r: fdt )
+
+ \ write reserve entry
+ 0 over !
+ cell+
+ 0 over !
+ cell+
+
+ \ copy string
+ 2dup fdt-strings @ swap rot move
+ + ( struct-len curfdt r: fdt )
+
+ \ copy struct
+ fdt-struct @ swap rot move ( r: fdt )
+
+ \ cleanup
+ fdt-struct @ 200000 free-mem
+ fdt-strings @ 10000 free-mem
+
+ \ return fdt
+ r>
+;
+
+: fdt-flatten-tree-free ( tree )
+ dup >fdth_tsize l@ free-mem
+;
+
s" /" find-node fdt-fix-phandles
diff --git a/board-qemu/slof/rtas.fs b/board-qemu/slof/rtas.fs
index 54d3929..5beb079 100644
--- a/board-qemu/slof/rtas.fs
+++ b/board-qemu/slof/rtas.fs
@@ -98,6 +98,10 @@ find-qemu-rtas
;
: rtas-quiesce ( -- )
+ " /" find-node
+ fdt-flatten-tree
+ dup hv-update-dt
+ fdt-flatten-tree-free
" quiesce" rtas-get-token rtas-cb rtas>token l!
0 rtas-cb rtas>nargs l!
0 rtas-cb rtas>nret l!
diff --git a/lib/libhvcall/hvcall.code b/lib/libhvcall/hvcall.code
index 8349748..6ff5715 100644
--- a/lib/libhvcall/hvcall.code
+++ b/lib/libhvcall/hvcall.code
@@ -136,3 +136,8 @@ PRIM(hv_X2d_update_X2d_phandle)
uint32_t old_phandle = TOS.u;
TOS.u = hv_generic(KVMPPC_H_UPDATE_PHANDLE, old_phandle, new_phandle);
MIRP
+
+PRIM(hv_X2d_update_X2d_dt)
+ unsigned long dt = TOS.u;
+ TOS.u = hv_generic(KVMPPC_H_UPDATE_DT, dt);
+MIRP
diff --git a/lib/libhvcall/hvcall.in b/lib/libhvcall/hvcall.in
index ab7513a..b59e3f7 100644
--- a/lib/libhvcall/hvcall.in
+++ b/lib/libhvcall/hvcall.in
@@ -32,4 +32,5 @@ cod(hv-logical-memop)
cod(hv-cas)
cod(hv-rtas-update)
cod(hv-update-phandle)
+cod(hv-update-dt)
cod(get-print-version)
--
2.11.0
More information about the SLOF
mailing list