diff --git a/lib/libhvcall/libhvcall.h b/lib/libhvcall/libhvcall.h
index 6356a62..3fa4398 100644
--- a/lib/libhvcall/libhvcall.h
+++ b/lib/libhvcall/libhvcall.h
@@ -24,7 +24,8 @@
 #define KVMPPC_H_LOGICAL_MEMOP  (KVMPPC_HCALL_BASE + 0x1)
 /* Client Architecture support */
 #define KVMPPC_H_CAS            (KVMPPC_HCALL_BASE + 0x2)
-#define KVMPPC_HCALL_MAX        KVMPPC_H_CAS
+#define KVMPPC_H_UPDATE_DT      (KVMPPC_HCALL_BASE + 0x3)
+#define KVMPPC_HCALL_MAX        KVMPPC_H_UPDATE_DT
 
 #ifndef __ASSEMBLY__
 
diff --git a/board-qemu/slof/fdt.fs b/board-qemu/slof/fdt.fs
index 851645e..2389659 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
@@ -69,7 +69,7 @@ fdt-start fdt-init
         dup >fdth_version l@ 3 >= IF
             ."  strings size     : 0x" dup >fdth_string_size l@ . cr
         THEN
-        dup >fdth_version l@ 17 >= IF
+        dup >fdth_version l@ 11 >= IF
             ."  struct size      : 0x" dup >fdth_struct_size l@ . cr
         THEN
     THEN
@@ -439,4 +439,290 @@ r> drop
     fdt-cas-fix?
 ;
 
+VARIABLE fdtfl-struct
+VARIABLE fdtfl-struct-here
+VARIABLE fdtfl-strings
+VARIABLE fdtfl-strings-cache
+VARIABLE fdtfl-strings-here
+VARIABLE fdtfl-strings-reused \ debug only
+VARIABLE fdt-ms \ debug only
+
+: 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 )
+    fdtfl-strings @
+    BEGIN
+        dup fdtfl-strings-cache @ <
+    WHILE
+        3dup zstring= IF
+            fdtfl-strings @ -
+            -rot
+            2drop
+            true
+            EXIT
+        THEN
+        fdt-skip-string
+    REPEAT
+    3drop
+    false
+;
+
+: fdt-str-allot ( len -- ) fdtfl-strings-here @ + to fdtfl-strings-here ;
+: fdt-str-c, ( char -- ) fdtfl-strings-here @ 1 fdt-str-allot c! ;
+: fdt-str-align  ( -- )
+    fdtfl-strings-here @
+    dup dup 4 #aligned swap -   ( here bytes-to-erase )
+    dup -rot
+    erase
+    fdt-str-allot
+;
+: fdt-str-bytes, ( data len -- ) fdtfl-strings-here @ over fdt-str-allot swap move ;
+: fdt-str-ztr, ( str len -- ) fdt-str-bytes, 0 fdt-str-c, ;
+
+: fdt-add-string ( name namelen -- nameoff )
+    fdtfl-strings-here @ -rot
+    fdt-str-ztr,
+    fdt-str-align
+    fdtfl-strings @ -
+;
+
+: fdt-get-string ( name namelen -- nameoff )
+    2dup fdt-find-string IF
+        -rot 2drop
+        fdt-debug IF
+           1 fdtfl-strings-reused +!
+        THEN
+        EXIT
+    THEN
+    fdt-add-string
+;
+
+: fdt-allot ( len -- ) fdtfl-struct-here @ + to fdtfl-struct-here ;
+: fdt-c, ( char -- ) fdtfl-struct-here @ 1 fdt-allot c! ;
+: fdt-align  ( -- )
+    fdtfl-struct-here @
+    dup dup 4 #aligned swap -   ( here bytes-to-erase )
+    dup -rot
+    erase
+    fdt-allot
+;
+: fdt-bytes, ( data len -- ) fdtfl-struct-here @ over fdt-allot swap move ;
+: fdt-ztr, ( str len -- ) fdt-bytes, 0 fdt-c, ;
+: fdt-l, ( token -- ) fdtfl-struct-here @ l! /l fdt-allot ;
+
+: fdt-begin-node ( name namelen -- )
+    OF_DT_BEGIN_NODE fdt-l,
+    2dup 1 = swap c@ [char] / = and  \ is it "/"?
+    IF
+        2drop s" " \ dtc is still unhappy though
+    THEN
+    fdt-ztr,
+    fdt-align
+;
+
+: fdt-end-node ( -- ) OF_DT_END_NODE fdt-l, ;
+
+: fdt-prop ( prop len name namelen -- )
+    OF_DT_PROP fdt-l,
+
+    \ get string offset
+    fdt-get-string      ( prop len nameoff )
+
+    \ store len and nameoff
+    over fdt-l,
+    fdt-l,              ( prop len )
+
+    \ now store the bytes
+    fdt-bytes,
+    fdt-align
+;
+
+: fdt-end ( -- ) OF_DT_END fdt-l, ;
+
+: fdt-properties ( phandle -- )
+    dup encode-int s" phandle" fdt-prop
+
+    node>properties @ cell+ @   ( cur )
+    BEGIN
+        dup
+    WHILE
+        dup link>               ( cur link )
+        dup >name name>string   ( cur link name len )
+        2dup s" name" str= IF
+           \ skipping "name" - it is useless
+            2drop               ( cur link )
+            drop                ( cur )
+        ELSE                    ( cur link name len )
+            2 pick              ( cur link name len link )
+            execute             ( cur link name len prop proplen )
+            2swap
+            fdt-prop            ( cur link )
+            drop
+        THEN
+        @
+    REPEAT
+    drop
+;
+
+: fdt-flatten-node ( node --  )
+    fdt-debug 1 > 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
+;
+
+: fdtfl-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 fdtfl-struct-here ! fdtfl-struct !
+    200000 alloc-mem dup fdtfl-strings-here ! fdtfl-strings !
+
+    fdt-debug IF
+        0 fdtfl-strings-reused !
+        milliseconds fdt-ms !
+    THEN
+
+    \ Preload strings cache
+    fdtfl-strings-preload
+    fdtfl-strings-here @ fdtfl-strings-cache !
+    \ Render the blobs
+    fdt-flatten-node
+    fdt-end
+
+    \ Calculate strings and struct sizes
+    fdtfl-struct-here @ fdtfl-struct @ -
+    fdtfl-strings-here @ fdtfl-strings @ - ( struct-len strings-len )
+
+    2dup + /fdth +
+    10 + \ Reserve 16 bytes and an empty reserved block
+
+    fdt-debug IF
+        3dup
+        ." FDTsize=" .d ." Strings=" .d ." Struct=" .d
+        ." Reused str=" fdtfl-strings-reused @ .d
+        milliseconds fdt-ms @ - .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!
+    11                  r@ >fdth_version l!
+    10                  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
+    fdtfl-strings @ fdt-append-blob
+    fdtfl-struct @ fdt-append-blob
+    drop
+
+    \ Free temporary blobs
+    fdtfl-struct @ 200000 free-mem
+    fdtfl-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 b17157e..219bcda 100644
--- a/board-qemu/slof/rtas.fs
+++ b/board-qemu/slof/rtas.fs
@@ -98,6 +98,13 @@ find-qemu-rtas
 ;
 
 : rtas-quiesce ( -- )
+    " /" find-node
+    fdt-flatten-tree
+    dup hv-update-dt ?dup IF
+        \ Ignore hcall not implemented error, print error otherwise
+        dup -2 <> IF ." HV-UPDATE-DT error: " . cr ELSE drop THEN
+    THEN
+    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 744469f..5918c90 100644
--- a/lib/libhvcall/hvcall.code
+++ b/lib/libhvcall/hvcall.code
@@ -123,3 +123,8 @@ PRIM(check_X2d_and_X2d_patch_X2d_sc1)
 
 	patch_broken_sc1((void*)start, (void*)end, (void*)patch_ins);
 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 e99d6d1..9193162 100644
--- a/lib/libhvcall/hvcall.in
+++ b/lib/libhvcall/hvcall.in
@@ -30,4 +30,5 @@ cod(RX!)
 
 cod(hv-logical-memop)
 cod(hv-cas)
+cod(hv-update-dt)
 cod(get-print-version)
