From patchwork Fri Sep 29 09:07:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 819843 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3y3Qgg4VMGz9t2m for ; Fri, 29 Sep 2017 19:07:43 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3y3Qgg3DfZzDrJ3 for ; Fri, 29 Sep 2017 19:07:43 +1000 (AEST) X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=ozlabs.ru (client-ip=107.173.13.209; helo=ozlabs.ru; envelope-from=aik@ozlabs.ru; receiver=) Received: from ozlabs.ru (ozlabs.ru [107.173.13.209]) by lists.ozlabs.org (Postfix) with ESMTP id 3y3Qgc3xhMzDrFt for ; Fri, 29 Sep 2017 19:07:39 +1000 (AEST) Received: from vpl1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id E320C3A60024; Fri, 29 Sep 2017 05:06:15 -0400 (EDT) From: Alexey Kardashevskiy To: slof@lists.ozlabs.org Date: Fri, 29 Sep 2017 19:07:29 +1000 Message-Id: <20170929090729.19871-1-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 Subject: [SLOF] [PATCH slof] fdt: Pass the resulting device tree to QEMU X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" 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 --- 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)