[SLOF] [PATCH slof v2] fdt: Pass the resulting device tree to QEMU
Greg Kurz
groug at kaod.org
Mon Oct 2 18:47:59 AEDT 2017
On Mon, 2 Oct 2017 16:38:19 +1100
Alexey Kardashevskiy <aik at ozlabs.ru> wrote:
> 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 20KB of strings), building such a tree takes
> ~2s on a POWER8 box. A simple tree with 1 CPU and a couple of devices
> takes 38ms and creates 16KB blob.
>
> This preloads strings with 40 property names from CPU and PCI device nodes
> and the strings lookup only searches within these. Without string reusing
> at all, the strings blob is 200KB and rendering time is 1.7sec; with
> unlimited reusing, the strings blob is 4KB and rendering time is 2.8sec.
>
> Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
> ---
>
> Changes:
> v2:
> * fixed comments from review
> * added strings cache
> * changed last_compat_vers from 0x17 to 0x16 as suggested by dwg
>
> ---
>
> I tested the blob by storing it from QEMU to a file 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 | 297 +++++++++++++++++++++++++++++++++++++++++++++-
> board-qemu/slof/rtas.fs | 4 +
> lib/libhvcall/hvcall.code | 5 +
> lib/libhvcall/hvcall.in | 1 +
> 5 files changed, 307 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)
Since KVMPPC_H_UPDATE_PHANDLE hasn't any user obviously, and is
supposed to be obsoleted by this patch, maybe you can revert it
in the first place, no ?
> +#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..ced9db3 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,299 @@ r> drop
> fdt-cas-fix?
> ;
>
> +VARIABLE fdt-struct
> +VARIABLE fdt-struct-cur
> +VARIABLE fdt-strings
> +VARIABLE fdt-strings-cache
> +VARIABLE fdt-strings-cur
> +VARIABLE fdt-strings-reused
> +VARIABLE fdt-ms
> +
> +\ Adds data to struct blob, also adds terminating null if name is added
> +: fdt-struct-add ( bytes len nullterminate -- )
> + >r
> + dup >r ( bytes len r: nullterminate len )
> + fdt-struct-cur @ swap ( bytes cur len r: nullterminate len )
> + \ copy bytes to structs
> + move
> + fdt-struct-cur @ ( cur r: nullterminate len )
> + \ increment fdt-struct-cur
> + r> + ( cur r: nullterminate )
> + \ add null if it is a string
> + r> IF
> + 0 over c!
> + 1+
> + THEN
> + \ and align to 4 bytes
> + 3 + -4 and
> + fdt-struct-cur !
> +;
> +
> +: fdt-encode-int ( token -- )
> + fdt-struct-cur @ l!
> + /l fdt-struct-cur +!
> +;
> +
> +: fdt-skip-string ( cur -- cur )
> + BEGIN
> + dup c@
> + WHILE
> + 1+
> + REPEAT
> + 4 + -4 and
> +;
> +
> +: zstring= ( str len zstr -- flag )
> + 2dup + c@ 0<> IF
> + 3drop false
> + EXIT
> + THEN
> + swap comp 0=
> +;
> +
> +: fdt-find-string ( name namelen -- nameoff true | false )
> + fdt-strings @
> + BEGIN
> + dup fdt-strings-cache @ <
> + WHILE
> + 3dup zstring= IF
> + fdt-strings @ -
> + -rot
> + 2drop
> + true
> + EXIT
> + THEN
> + fdt-skip-string
> + REPEAT
> + 3drop
> + false
> +;
> +
> +: fdt-add-string ( name namelen -- nameoff )
> + fdt-strings-cur @
> + fdt-strings @ - >r ( name namelen r: nameoff )
> + dup >r ( name namelen r: nameoff namelen )
> +
> + \ copy string
> + fdt-strings-cur @ swap ( name cur namelen r: nameoff namelen )
> + move ( r: nameoff namelen )
> +
> + \ increment cur and null terminate
> + fdt-strings-cur @
> + r> + ( cur r: nameoff )
> + \ add null if it is a string
> + 0 over c!
> + \ add 1 byte for the null and align to 4 bytes
> + 4 + -4 and
> + fdt-strings-cur ! ( r: nameoff )
> + r> ( nameoff )
> +;
> +
> +: fdt-get-string ( name namelen -- nameoff )
> + 2dup fdt-find-string IF
> + -rot 2drop
> + fdt-debug IF
> + 1 fdt-strings-reused +!
> + THEN
> + EXIT
> + THEN
> + fdt-add-string
> +;
> +
> +: fdt-begin-node ( name namelen -- )
> + OF_DT_BEGIN_NODE fdt-encode-int
> + 2dup 1 = swap c@ [char] / = and \ is it "/"?
> + IF
> + 2drop s" " \ dtc is still unhappy though
> + THEN
> + true fdt-struct-add
> +;
> +
> +: fdt-end-node ( -- )
> + OF_DT_END_NODE fdt-encode-int
> +;
> +
> +: fdt-prop ( prop len name namelen -- )
> + OF_DT_PROP fdt-encode-int
> +
> + \ get string offset
> + fdt-get-string ( prop len nameoff )
> +
> + \ store len and nameoff
> + over fdt-encode-int
> + fdt-encode-int ( prop len )
> +
> + \ now add the bytes
> + false fdt-struct-add
> +;
> +
> +: fdt-end ( -- )
> + OF_DT_END fdt-encode-int
> +;
> +
> +: fdt-properties ( phandle -- )
> + dup encode-int s" phandle" fdt-prop
> + >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-strings-preload ( -- )
> + s" reg" fdt-add-string drop
> + s" status" fdt-add-string drop
> + s" 64-bit" fdt-add-string drop
> + s" phandle" fdt-add-string drop
> + s" ibm,vmx" fdt-add-string drop
> + s" ibm,dfp" fdt-add-string drop
> + s" slb-size" fdt-add-string drop
> + s" ibm,purr" fdt-add-string drop
> + s" vendor-id" fdt-add-string drop
> + s" device-id" fdt-add-string drop
> + s" min-grant" fdt-add-string drop
> + s" class-code" fdt-add-string drop
> + s" compatible" fdt-add-string drop
> + s" interrupts" fdt-add-string drop
> + s" cpu-version" fdt-add-string drop
> + s" #size-cells" fdt-add-string drop
> + s" ibm,req#msi" fdt-add-string drop
> + s" revision-id" fdt-add-string drop
> + s" device_type" fdt-add-string drop
> + s" max-latency" fdt-add-string drop
> + s" ibm,chip-id" fdt-add-string drop
> + s" ibm,pft-size" fdt-add-string drop
> + s" ibm,slb-size" fdt-add-string drop
> + s" devsel-speed" fdt-add-string drop
> + s" ibm,loc-code" fdt-add-string drop
> + s" subsystem-id" fdt-add-string drop
> + s" d-cache-size" fdt-add-string drop
> + s" i-cache-size" fdt-add-string drop
> + s" #address-cells" fdt-add-string drop
> + s" clock-frequency" fdt-add-string drop
> + s" cache-line-size" fdt-add-string drop
> + s" ibm,pa-features" fdt-add-string drop
> + s" ibm,my-drc-index" fdt-add-string drop
> + s" d-cache-line-size" fdt-add-string drop
> + s" i-cache-line-size" fdt-add-string drop
> + s" assigned-addresses" fdt-add-string drop
> + s" d-cache-block-size" fdt-add-string drop
> + s" i-cache-block-size" fdt-add-string drop
> + s" timebase-frequency" fdt-add-string drop
> + s" subsystem-vendor-id" fdt-add-string drop
> + s" ibm,segment-page-sizes" fdt-add-string drop
> + s" ibm,ppc-interrupt-server#s" fdt-add-string drop
> + s" ibm,processor-segment-sizes" fdt-add-string drop
> + s" ibm,ppc-interrupt-gserver#s" fdt-add-string drop
> +;
> +
> +: fdt-append-blob ( bytes cur blob -- cur )
> + 3dup -rot swap move
> + drop +
> +;
> +
> +: fdt-flatten-tree ( root -- tree )
> + 200000 alloc-mem dup fdt-struct-cur ! fdt-struct !
> + 200000 alloc-mem dup fdt-strings-cur ! fdt-strings !
> +
> + fdt-debug IF
> + 0 fdt-strings-reused !
> + milliseconds fdt-ms !
> + THEN
> +
> + \ Preload strings cache
> + fdt-strings-preload
> + fdt-strings-cur @ fdt-strings-cache !
> + \ Render the blobs
> + fdt-flatten-node
> + fdt-end
> +
> + \ Calculate strings and struct sizes
> + fdt-struct-cur @ fdt-struct @ -
> + fdt-strings-cur @ fdt-strings @ - ( struct-len strings-len )
> +
> + 2dup + /fdth +
> + 10 + \ Reserve 16 bytes and an empty reserved block
> +
> + fdt-debug IF
> + 3dup
> + ." FDT flat size=" .d cr
> + ." Strings size=" .d cr
> + ." Struct size=" .d cr
> + ." Reused strings=" fdt-strings-reused @ .d cr
> + milliseconds fdt-ms @ -
> + ." Took " .d ." ms" cr
> + THEN
> +
> + \ Allocate flatten DT blob
> + dup alloc-mem ( struct-len strings-len total-len fdt )
> + >r ( struct-len strings-len total-len 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!
> + 16 r@ >fdth_compat_vers l!
> + 0 r@ >fdth_boot_cpu l!
> + over r@ >fdth_string_size l!
> + 2 pick r@ >fdth_struct_size l!
> + ( struct-len strings-len total-len r: fdt )
> +
> + drop ( struct-len strings-len r: fdt )
> + r@ /fdth + ( struct-len strings-len cur r: fdt )
> +
> + \ Write the reserved entry
> + 0 over !
> + cell+
> + 0 over !
> + cell+ ( struct-len strings-len cur r: fdt )
> +
> + \ Write strings and struct blobs
> + fdt-strings @ fdt-append-blob
> + fdt-struct @ fdt-append-blob
> + drop
> +
> + \ Free temporary blobs
> + fdt-struct @ 200000 free-mem
> + fdt-strings @ 200000 free-mem
> +
> + \ Return fdt
> + r>
> +;
> +
> +: fdt-flatten-tree-free ( tree )
> + dup >fdth_tsize l@ free-mem
> +;
> +
> +: fdt ( -- )
> + " /" find-node
> + fdt-flatten-tree
> +;
> +
> 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)
More information about the SLOF
mailing list