[SLOF] [PATCH slof] fdt: Pass the resulting device tree to QEMU

Alexey Kardashevskiy aik at ozlabs.ru
Sat Sep 30 09:54:49 AEST 2017


On 29/09/17 19:07, Alexey Kardashevskiy 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 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 -- )


Missing here:

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-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)
> 


-- 
Alexey


More information about the SLOF mailing list