diff mbox series

fdt: Pass the resulting device tree to QEMU

Message ID 20170929090729.19871-1-aik@ozlabs.ru
State Superseded
Headers show
Series fdt: Pass the resulting device tree to QEMU | expand

Commit Message

Alexey Kardashevskiy Sept. 29, 2017, 9:07 a.m. UTC
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@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@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(-)

Comments

Alexey Kardashevskiy Sept. 29, 2017, 9:21 a.m. UTC | #1
Forgot to cc: Balbir, he _wants_ to learn Forth/SLOF :-D


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@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@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)
>
Alexey Kardashevskiy Sept. 29, 2017, 11:48 p.m. UTC | #2
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@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@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


Forgot to mention - the resulting tree does not phandles (which is the
whole purpose of the patch), I'll have to add them manually :)
Alexey Kardashevskiy Sept. 29, 2017, 11:54 p.m. UTC | #3
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@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@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)
>
Segher Boessenkool Oct. 1, 2017, 7:34 p.m. UTC | #4
Hi Alexey,

Just some random comments, not a full review:

On Fri, Sep 29, 2017 at 07:07:29PM +1000, Alexey Kardashevskiy wrote:
> +: 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 !
> +;

You want a comment on this function, and you probably want a convenience
word to do the zero-termination (e.g. fdt-struct-add-zero-terminated).

> +: fdt-add-long ( token -- )
> +    fdt-struct-cur @
> +    l!
> +    fdt-struct-cur @
> +    4 +
> +    fdt-struct-cur !
> +;

: fdt-add-long ( token -- )
   fdt-struct-cur @ l!  /l fdt-struct-cur +! ;

"add" is not such a great name, maybe you should name this like property
encoding (and maybe structure it like it even), so fdt-encode-int etc.?

> +: skip-to-next ( cur -- cur )
> +    BEGIN
> +        dup c@
> +    WHILE
> +        1+
> +    REPEAT
> +    4 + -4 and
> +;

: skip-to-next ( addr -- addr )  dup zcount + 1+ 4 #aligned ;

Skip to next what?  "fdt-skip-string" perhaps?

> +: 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
> +;

So "str" is a zero-terminated string here.

: zstring=  ( str len zstr -- flag )
   2dup + c@ IF 3drop false EXIT THEN  swap comp 0= ;

\ Not a great name, it does this "reused" thing, too?
: string-equal ( name namelen str -- true | false )
   zstring= dup IF 1 fdt-strings-reused +! ;

> +: fdt-get-string ( name namelen -- nameoff )
> +    \ lookup
> +    fdt-strings @
> +    BEGIN
> +        dup fdt-strings-cur @
> +        = not

Don't use NOT, it does not do what you think (it is INVERT, but you want
0= here; could just say <> of course).

This word is so big that it is very hard to follow, btw.

> +: fdt-begin-node ( name namelen -- )
> +    OF_DT_BEGIN_NODE fdt-add-long
> +    2dup 1 = swap c@ 2F = and  \ is it "/"?

This would be ideal for COMPARE except that was never implemented ;-)
   s" /" compare
(It's also probably more readable to write   [char] /   instead of 2F,
if you don't want to use the string words).

I think this takes so long on huge device trees because you do way too
many string compares, but it is hard to tell.


Segher
Alexey Kardashevskiy Oct. 2, 2017, 1:08 a.m. UTC | #5
On 02/10/17 06:34, Segher Boessenkool wrote:
> Hi Alexey,
> 
> Just some random comments, not a full review:
> 
> On Fri, Sep 29, 2017 at 07:07:29PM +1000, Alexey Kardashevskiy wrote:
>> +: 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 !
>> +;
> 
> You want a comment on this function,

You mean text comments, not just stack comments? Ok.

> and you probably want a convenience
> word to do the zero-termination (e.g. fdt-struct-add-zero-terminated).

Seeing too many fdt-struct-cur hurts my eyes so I'd rather not.


> 
>> +: fdt-add-long ( token -- )
>> +    fdt-struct-cur @
>> +    l!
>> +    fdt-struct-cur @
>> +    4 +
>> +    fdt-struct-cur !
>> +;
> 
> : fdt-add-long ( token -- )
>    fdt-struct-cur @ l!  /l fdt-struct-cur +! ;
> 
> "add" is not such a great name, maybe you should name this like property
> encoding (and maybe structure it like it even), so fdt-encode-int etc.?
> 
>> +: skip-to-next ( cur -- cur )
>> +    BEGIN
>> +        dup c@
>> +    WHILE
>> +        1+
>> +    REPEAT
>> +    4 + -4 and
>> +;
> 
> : skip-to-next ( addr -- addr )  dup zcount + 1+ 4 #aligned ;
> 
> Skip to next what?  "fdt-skip-string" perhaps?
> 
>> +: 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
>> +;
> 
> So "str" is a zero-terminated string here.
> 
> : zstring=  ( str len zstr -- flag )
>    2dup + c@ IF 3drop false EXIT THEN  swap comp 0= ;

Thanks, this is better :)

But - is it really necessary to make words a single line? What is exactly
that you win when you do this? It is really hard to read.


> \ Not a great name, it does this "reused" thing, too?
> : string-equal ( name namelen str -- true | false )
>    zstring= dup IF 1 fdt-strings-reused +! ;


My bad, "reused" thing is a leftover from debug code which tells how many
strings this has saved, you can ignore it.


>> +: fdt-get-string ( name namelen -- nameoff )
>> +    \ lookup
>> +    fdt-strings @
>> +    BEGIN
>> +        dup fdt-strings-cur @
>> +        = not
> 
> Don't use NOT, it does not do what you think (it is INVERT, but you want
> 0= here; could just say <> of course).

Yup, a bug, thanks.

> 
> This word is so big that it is very hard to follow, btw.

Hmmm. I'll split out the lookup bit. fdt-flatten-tree is even bigger but
you did not make the same comment about it.

>
>> +: fdt-begin-node ( name namelen -- )
>> +    OF_DT_BEGIN_NODE fdt-add-long
>> +    2dup 1 = swap c@ 2F = and  \ is it "/"?
> 
> This would be ideal for COMPARE except that was never implemented ;-)
>    s" /" compare
> (It's also probably more readable to write   [char] /   instead of 2F,
> if you don't want to use the string words).

Sure, it has just been a while since I touched forth :)


> 
> I think this takes so long on huge device trees because you do way too
> many string compares, but it is hard to tell.

I'll double check but 2.8sec on such a massive guest is really not much as
the rest takes lot lot more time.

Thanks for the comment. Are you still going to do the full review or I can
respin? :)


One question while I remember: firstly I looked at how "(.properties)" and
".property" work and these things do not use "next-property", it is
node>properties, link>, etc - is this described somewhere (1275?) or it is
the SLOF implementation detail? It is probably faster but definitely harder
to read.
Segher Boessenkool Oct. 2, 2017, 10:16 a.m. UTC | #6
Hi!

On Mon, Oct 02, 2017 at 12:08:32PM +1100, Alexey Kardashevskiy wrote:
> On 02/10/17 06:34, Segher Boessenkool wrote:
> > On Fri, Sep 29, 2017 at 07:07:29PM +1000, Alexey Kardashevskiy wrote:
> >> +: 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 !
> >> +;
> > 
> > You want a comment on this function,
> 
> You mean text comments, not just stack comments? Ok.

Yeah, a comment on what the word does, since the name doesn't make it
obvious.  Better is to have a better name, but I can't think of any
either.  Maybe this needs to factored a bit better?

> > and you probably want a convenience
> > word to do the zero-termination (e.g. fdt-struct-add-zero-terminated).
> 
> Seeing too many fdt-struct-cur hurts my eyes so I'd rather not.

Yeah.

So maybe something like

VALUE fdt-here  \ instead of fdt-struct-cur
: fdt-allot  fdt-here + to fdt-here ;
: fdt-c,  fdt-here  1 fdt-allot  c! ;
: fdt-align  fdt-here 4 #aligned fdt-here - ; \ or fill with zeroes?
: fdt-str, ( str len -- )  fdt-here over fdt-allot  swap move ;
: fdt-ztr, ( str len -- )  fdt-str,  0 fdt-c, ;
\ and now use   fdt-str, fdt-align   instead of   false fdt-struct-add
\ and just  fdt-ztr, fdt-align   for   true fdt-struct-add

> >> +: fdt-add-long ( token -- )
> >> +    fdt-struct-cur @
> >> +    l!
> >> +    fdt-struct-cur @
> >> +    4 +
> >> +    fdt-struct-cur !
> >> +;
> > 
> > : fdt-add-long ( token -- )
> >    fdt-struct-cur @ l!  /l fdt-struct-cur +! ;

This would be   fdt-l,   then.  Using similar names to the standard data
space allocation words makes things easy to understand (and these are a
known good design so you don't have to spend time designing a good
interface :-) )

> > So "str" is a zero-terminated string here.
> > 
> > : zstring=  ( str len zstr -- flag )
> >    2dup + c@ IF 3drop false EXIT THEN  swap comp 0= ;
> 
> Thanks, this is better :)
> 
> But - is it really necessary to make words a single line? What is exactly
> that you win when you do this? It is really hard to read.

You can use whatever style you like best :-)  I find this more readable,
or perhaps

: zstring=  ( str len zstr -- flag )
   2dup + c@ IF
     3drop false EXIT THEN
   swap comp 0= ;

if you want to be fancy.  It's a good idea to keep your words short and
sweet, and then indent etc. doesn't matter anyway.

> My bad, "reused" thing is a leftover from debug code which tells how many
> strings this has saved, you can ignore it.

Ah :-)

> > This word is so big that it is very hard to follow, btw.
> 
> Hmmm. I'll split out the lookup bit. fdt-flatten-tree is even bigger but
> you did not make the same comment about it.

But fdt-flatten-tree is mostly a list of things to do in order.

I didn't comment on it because I haven't reviewed the whole thing, btw.

> > I think this takes so long on huge device trees because you do way too
> > many string compares, but it is hard to tell.
> 
> I'll double check but 2.8sec on such a massive guest is really not much as
> the rest takes lot lot more time.

Ah, right.  You have to create that tree in the first place already :-)

> Thanks for the comment. Are you still going to do the full review or I can
> respin? :)

Sure, but it will be a while.

> One question while I remember: firstly I looked at how "(.properties)" and
> ".property" work and these things do not use "next-property", it is
> node>properties, link>, etc - is this described somewhere (1275?) or it is
> the SLOF implementation detail? It is probably faster but definitely harder
> to read.

Implementation details.

node>properties is defined in node.fs, it just gets the address of a
struct field.

The properties are not a linked list, but a Forth wordlist.  This is a)
faster, because wordlists are optimised a bit, say ten times faster; and
b) this allows use to run any code we want to get a property, not just
lookups of static data.  From property.fs:

\ Words on the property list for a node are actually executable words,
\ that return the address and length of the property's data.  Special
\ nodes like /options can have their properties use specialized code to
\ dynamically generate their data; most nodes just use a 2CONSTANT.


Segher
Alexey Kardashevskiy Oct. 2, 2017, 11:09 a.m. UTC | #7
On 02/10/17 21:16, Segher Boessenkool wrote:
> Hi!
> 
> On Mon, Oct 02, 2017 at 12:08:32PM +1100, Alexey Kardashevskiy wrote:
>> On 02/10/17 06:34, Segher Boessenkool wrote:
>>> On Fri, Sep 29, 2017 at 07:07:29PM +1000, Alexey Kardashevskiy wrote:
>>>> +: 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 !
>>>> +;
>>>
>>> You want a comment on this function,
>>
>> You mean text comments, not just stack comments? Ok.
> 
> Yeah, a comment on what the word does, since the name doesn't make it
> obvious.  Better is to have a better name, but I can't think of any
> either.  Maybe this needs to factored a bit better?
> 
>>> and you probably want a convenience
>>> word to do the zero-termination (e.g. fdt-struct-add-zero-terminated).
>>
>> Seeing too many fdt-struct-cur hurts my eyes so I'd rather not.
> 
> Yeah.
> 
> So maybe something like
> 
> VALUE fdt-here  \ instead of fdt-struct-cur
> : fdt-allot  fdt-here + to fdt-here ;

: fdt-allot ( len -- ) fdt-here + to fdt-here ;
may be?

I am missing something here, the words below assume that fdt-alloc returns
something :-/


> : fdt-c,  fdt-here  1 fdt-allot  c! ;
> : fdt-align  fdt-here 4 #aligned fdt-here - ; \ or fill with zeroes?
> : fdt-str, ( str len -- )  fdt-here over fdt-allot  swap move ;
> : fdt-ztr, ( str len -- )  fdt-str,  0 fdt-c, ;
> \ and now use   fdt-str, fdt-align   instead of   false fdt-struct-add
> \ and just  fdt-ztr, fdt-align   for   true fdt-struct-add
> 
>>>> +: fdt-add-long ( token -- )
>>>> +    fdt-struct-cur @
>>>> +    l!
>>>> +    fdt-struct-cur @
>>>> +    4 +
>>>> +    fdt-struct-cur !
>>>> +;
>>>
>>> : fdt-add-long ( token -- )
>>>    fdt-struct-cur @ l!  /l fdt-struct-cur +! ;
> 
> This would be   fdt-l,   then.  Using similar names to the standard data
> space allocation words makes things easy to understand (and these are a
> known good design so you don't have to spend time designing a good
> interface :-) )
> 
>>> So "str" is a zero-terminated string here.
>>>
>>> : zstring=  ( str len zstr -- flag )
>>>    2dup + c@ IF 3drop false EXIT THEN  swap comp 0= ;
>>
>> Thanks, this is better :)
>>
>> But - is it really necessary to make words a single line? What is exactly
>> that you win when you do this? It is really hard to read.
> 
> You can use whatever style you like best :-)  I find this more readable,
> or perhaps
> 
> : zstring=  ( str len zstr -- flag )
>    2dup + c@ IF
>      3drop false EXIT THEN
>    swap comp 0= ;
> 
> if you want to be fancy.  It's a good idea to keep your words short and
> sweet, and then indent etc. doesn't matter anyway.
> 
>> My bad, "reused" thing is a leftover from debug code which tells how many
>> strings this has saved, you can ignore it.
> 
> Ah :-)
> 
>>> This word is so big that it is very hard to follow, btw.
>>
>> Hmmm. I'll split out the lookup bit. fdt-flatten-tree is even bigger but
>> you did not make the same comment about it.
> 
> But fdt-flatten-tree is mostly a list of things to do in order.
> 
> I didn't comment on it because I haven't reviewed the whole thing, btw.
> 
>>> I think this takes so long on huge device trees because you do way too
>>> many string compares, but it is hard to tell.
>>
>> I'll double check but 2.8sec on such a massive guest is really not much as
>> the rest takes lot lot more time.
> 
> Ah, right.  You have to create that tree in the first place already :-)
> 
>> Thanks for the comment. Are you still going to do the full review or I can
>> respin? :)
> 
> Sure, but it will be a while.

I got a bit bored on a Labour Day (today, in ACT) and posted v2 :) Do you
want to me to post v3 with  fdt-allot & friends first?


> 
>> One question while I remember: firstly I looked at how "(.properties)" and
>> ".property" work and these things do not use "next-property", it is
>> node>properties, link>, etc - is this described somewhere (1275?) or it is
>> the SLOF implementation detail? It is probably faster but definitely harder
>> to read.
> 
> Implementation details.
> 
> node>properties is defined in node.fs, it just gets the address of a
> struct field.
> 
> The properties are not a linked list, but a Forth wordlist.  This is a)
> faster, because wordlists are optimised a bit, say ten times faster; and
> b) this allows use to run any code we want to get a property, not just
> lookups of static data.  From property.fs:
> 
> \ Words on the property list for a node are actually executable words,
> \ that return the address and length of the property's data.  Special
> \ nodes like /options can have their properties use specialized code to
> \ dynamically generate their data; most nodes just use a 2CONSTANT.

Hm. I wonder if it makes sense to rewrite fdt-properties using this.
Segher Boessenkool Oct. 2, 2017, 3:12 p.m. UTC | #8
On Mon, Oct 02, 2017 at 10:09:52PM +1100, Alexey Kardashevskiy wrote:
> > So maybe something like
> > 
> > VALUE fdt-here  \ instead of fdt-struct-cur
> > : fdt-allot  fdt-here + to fdt-here ;
> 
> : fdt-allot ( len -- ) fdt-here + to fdt-here ;
> may be?
> 
> I am missing something here, the words below assume that fdt-alloc returns
> something :-/
> 
> > : fdt-c,  fdt-here  1 fdt-allot  c! ;
> > : fdt-align  fdt-here 4 #aligned fdt-here - ; \ or fill with zeroes?
> > : fdt-str, ( str len -- )  fdt-here over fdt-allot  swap move ;
> > : fdt-ztr, ( str len -- )  fdt-str,  0 fdt-c, ;
> > \ and now use   fdt-str, fdt-align   instead of   false fdt-struct-add
> > \ and just  fdt-ztr, fdt-align   for   true fdt-struct-add

I don't see it, but I haven't tested it either, just typed it :-)

: fdt-str, ( str len -- )
  fdt-here over ( str len fhere len )
  fdt-allot ( str len fhere )
  swap ( str fhere len )
  move ( -- )
;

Looks fine to me?

> >> Thanks for the comment. Are you still going to do the full review or I can
> >> respin? :)
> > 
> > Sure, but it will be a while.
> 
> I got a bit bored on a Labour Day (today, in ACT) and posted v2 :) Do you
> want to me to post v3 with  fdt-allot & friends first?

If you think those suggestions help, then yes please.

> > The properties are not a linked list, but a Forth wordlist.  This is a)
> > faster, because wordlists are optimised a bit, say ten times faster; and
> > b) this allows use to run any code we want to get a property, not just
> > lookups of static data.  From property.fs:
> > 
> > \ Words on the property list for a node are actually executable words,
> > \ that return the address and length of the property's data.  Special
> > \ nodes like /options can have their properties use specialized code to
> > \ dynamically generate their data; most nodes just use a 2CONSTANT.
> 
> Hm. I wonder if it makes sense to rewrite fdt-properties using this.

You might need to make a case-sensitive wordlist search then?


Segher
Alexey Kardashevskiy Oct. 3, 2017, 4:33 a.m. UTC | #9
On 03/10/17 02:12, Segher Boessenkool wrote:
> On Mon, Oct 02, 2017 at 10:09:52PM +1100, Alexey Kardashevskiy wrote:
>>> So maybe something like
>>>
>>> VALUE fdt-here  \ instead of fdt-struct-cur
>>> : fdt-allot  fdt-here + to fdt-here ;
>>
>> : fdt-allot ( len -- ) fdt-here + to fdt-here ;
>> may be?
>>
>> I am missing something here, the words below assume that fdt-alloc returns
>> something :-/
>>
>>> : fdt-c,  fdt-here  1 fdt-allot  c! ;
>>> : fdt-align  fdt-here 4 #aligned fdt-here - ; \ or fill with zeroes?
>>> : fdt-str, ( str len -- )  fdt-here over fdt-allot  swap move ;
>>> : fdt-ztr, ( str len -- )  fdt-str,  0 fdt-c, ;
>>> \ and now use   fdt-str, fdt-align   instead of   false fdt-struct-add
>>> \ and just  fdt-ztr, fdt-align   for   true fdt-struct-add
> 
> I don't see it, but I haven't tested it either, just typed it :-)
> 
> : fdt-str, ( str len -- )
>   fdt-here over ( str len fhere len )
>   fdt-allot ( str len fhere )
>   swap ( str fhere len )
>   move ( -- )
> ;
> 
> Looks fine to me?
> 
>>>> Thanks for the comment. Are you still going to do the full review or I can
>>>> respin? :)
>>>
>>> Sure, but it will be a while.
>>
>> I got a bit bored on a Labour Day (today, in ACT) and posted v2 :) Do you
>> want to me to post v3 with  fdt-allot & friends first?
> 
> If you think those suggestions help, then yes please.

I'd rather follow the style and who knows it better than you :)
v3 is coming soon.

>>> The properties are not a linked list, but a Forth wordlist.  This is a)
>>> faster, because wordlists are optimised a bit, say ten times faster; and
>>> b) this allows use to run any code we want to get a property, not just
>>> lookups of static data.  From property.fs:
>>>
>>> \ Words on the property list for a node are actually executable words,
>>> \ that return the address and length of the property's data.  Special
>>> \ nodes like /options can have their properties use specialized code to
>>> \ dynamically generate their data; most nodes just use a 2CONSTANT.
>>
>> Hm. I wonder if it makes sense to rewrite fdt-properties using this.
> 
> You might need to make a case-sensitive wordlist search then?

I have no idea, any example? I'll probably skip this bit this time though.
Segher Boessenkool Oct. 4, 2017, 1:39 p.m. UTC | #10
On Tue, Oct 03, 2017 at 03:33:16PM +1100, Alexey Kardashevskiy wrote:
> On 03/10/17 02:12, Segher Boessenkool wrote:
> > On Mon, Oct 02, 2017 at 10:09:52PM +1100, Alexey Kardashevskiy wrote:
> >>> : fdt-c,  fdt-here  1 fdt-allot  c! ;
> >>> : fdt-align  fdt-here 4 #aligned fdt-here - ; \ or fill with zeroes?
> >>> : fdt-str, ( str len -- )  fdt-here over fdt-allot  swap move ;
> >>> : fdt-ztr, ( str len -- )  fdt-str,  0 fdt-c, ;
> >>> \ and now use   fdt-str, fdt-align   instead of   false fdt-struct-add
> >>> \ and just  fdt-ztr, fdt-align   for   true fdt-struct-add
> > 
> > I don't see it, but I haven't tested it either, just typed it :-)
> > 
> > : fdt-str, ( str len -- )
> >   fdt-here over ( str len fhere len )
> >   fdt-allot ( str len fhere )
> >   swap ( str fhere len )
> >   move ( -- )
> > ;
> > 
> > Looks fine to me?

Well,

: fdt-str, ( str len -- )  dup fdt-allot  fdt-here swap move ;

is probably clearer :-)

> >>> The properties are not a linked list, but a Forth wordlist.  This is a)
> >>> faster, because wordlists are optimised a bit, say ten times faster; and
> >>> b) this allows use to run any code we want to get a property, not just
> >>> lookups of static data.  From property.fs:
> >>>
> >>> \ Words on the property list for a node are actually executable words,
> >>> \ that return the address and length of the property's data.  Special
> >>> \ nodes like /options can have their properties use specialized code to
> >>> \ dynamically generate their data; most nodes just use a 2CONSTANT.
> >>
> >> Hm. I wonder if it makes sense to rewrite fdt-properties using this.
> > 
> > You might need to make a case-sensitive wordlist search then?
> 
> I have no idea, any example? I'll probably skip this bit this time though.

Currently deep down all wordlists use string=ci (that is, case-insensitive
string compare).  I think for the FDT string table you will want case-
sensitive instead.

(When searching the Forth dictionaries Open Firmware requires case-
insensitive; and upper case is not allowed in property names, so doing
a case-insensitive search works there, too (at least in practice, even
though people *do* use upper case in property names).

One option is to set some global flag before finding a word; another is
to have a separate word for case-sentive finding; yet another is to set
a flag in the wordlist itself saying if it should be case-sensitive.
That last one is probably the most useful for other purposes, too.


Segher
David Gibson Oct. 4, 2017, 11:23 p.m. UTC | #11
On Wed, Oct 04, 2017 at 08:39:59AM -0500, Segher Boessenkool wrote:
> On Tue, Oct 03, 2017 at 03:33:16PM +1100, Alexey Kardashevskiy wrote:
> > On 03/10/17 02:12, Segher Boessenkool wrote:
> > > On Mon, Oct 02, 2017 at 10:09:52PM +1100, Alexey Kardashevskiy wrote:
> > >>> : fdt-c,  fdt-here  1 fdt-allot  c! ;
> > >>> : fdt-align  fdt-here 4 #aligned fdt-here - ; \ or fill with zeroes?
> > >>> : fdt-str, ( str len -- )  fdt-here over fdt-allot  swap move ;
> > >>> : fdt-ztr, ( str len -- )  fdt-str,  0 fdt-c, ;
> > >>> \ and now use   fdt-str, fdt-align   instead of   false fdt-struct-add
> > >>> \ and just  fdt-ztr, fdt-align   for   true fdt-struct-add
> > > 
> > > I don't see it, but I haven't tested it either, just typed it :-)
> > > 
> > > : fdt-str, ( str len -- )
> > >   fdt-here over ( str len fhere len )
> > >   fdt-allot ( str len fhere )
> > >   swap ( str fhere len )
> > >   move ( -- )
> > > ;
> > > 
> > > Looks fine to me?
> 
> Well,
> 
> : fdt-str, ( str len -- )  dup fdt-allot  fdt-here swap move ;
> 
> is probably clearer :-)
> 
> > >>> The properties are not a linked list, but a Forth wordlist.  This is a)
> > >>> faster, because wordlists are optimised a bit, say ten times faster; and
> > >>> b) this allows use to run any code we want to get a property, not just
> > >>> lookups of static data.  From property.fs:
> > >>>
> > >>> \ Words on the property list for a node are actually executable words,
> > >>> \ that return the address and length of the property's data.  Special
> > >>> \ nodes like /options can have their properties use specialized code to
> > >>> \ dynamically generate their data; most nodes just use a 2CONSTANT.
> > >>
> > >> Hm. I wonder if it makes sense to rewrite fdt-properties using this.
> > > 
> > > You might need to make a case-sensitive wordlist search then?
> > 
> > I have no idea, any example? I'll probably skip this bit this time though.
> 
> Currently deep down all wordlists use string=ci (that is, case-insensitive
> string compare).  I think for the FDT string table you will want case-
> sensitive instead.

Yes, absolutely.

> (When searching the Forth dictionaries Open Firmware requires case-
> insensitive; and upper case is not allowed in property names, so doing
> a case-insensitive search works there, too (at least in practice, even
> though people *do* use upper case in property names).

Right.  There are, alas, a number of things that aren't allowed which
are nonetheless found in the wild.

Plus, a case insensitve comparison should be faster.

> One option is to set some global flag before finding a word; another is
> to have a separate word for case-sentive finding; yet another is to set
> a flag in the wordlist itself saying if it should be case-sensitive.
> That last one is probably the most useful for other purposes, too.
> 
> 
> Segher
> _______________________________________________
> SLOF mailing list
> SLOF@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/slof
diff mbox series

Patch

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)