[SLOF] [PATCH slof] rtas: Integrate RTAS blob

Alexey Kardashevskiy aik at ozlabs.ru
Tue Jul 16 15:11:31 AEST 2019


We implement RTAS as a simple binary blob which calls directly into QEMU
via a custom hcall. So far we were relying on QEMU putting the RTAS blob
to the guest memory with its location in linux,rtas-base/rtas-size.

The problems with this are:
1. we need to peek a location in the guest ram in addition to slof, FDT
and sometime kernel and init ram disk; having one less image makes QEMU's
life easier.
2. for secure VMs, it is yet another image which needs to be signed and
verified.

This implements "instantiate-rtas" completely in SLOF, including KVM PR
support ("broken sc1").

Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
---
 lib/libhvcall/libhvcall.h |  4 ++++
 lib/libhvcall/brokensc1.c |  2 +-
 board-qemu/slof/rtas.fs   | 44 +++++++++++++--------------------------
 lib/libhvcall/hvcall.S    | 19 +++++++++++++++++
 lib/libhvcall/hvcall.code | 22 ++++++++++++++++++++
 lib/libhvcall/hvcall.in   |  2 ++
 6 files changed, 62 insertions(+), 31 deletions(-)

diff --git a/lib/libhvcall/libhvcall.h b/lib/libhvcall/libhvcall.h
index caa4d6d3f17f..bd402be3fa48 100644
--- a/lib/libhvcall/libhvcall.h
+++ b/lib/libhvcall/libhvcall.h
@@ -97,11 +97,15 @@ extern unsigned long hv_logical_ci_store(unsigned long size, unsigned long addr,
 extern unsigned long hv_logical_memop(unsigned long dst, unsigned long src,
 				      unsigned long esize, unsigned long count,
 				      unsigned long op);
+extern int check_broken_sc1(void);
 extern int patch_broken_sc1(void *start, void *end, uint32_t *test_ins);
 
 extern unsigned long hv_cas(unsigned long vec, unsigned long buf,
 			unsigned long size);
 
+extern void *hv_rtas, *hv_rtas_end;
+extern void *hv_rtas_broken_sc1, *hv_rtas_broken_sc1_end;
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __LIBHVCALL_H__ */
diff --git a/lib/libhvcall/brokensc1.c b/lib/libhvcall/brokensc1.c
index d97ae77558c7..f01157029b8a 100644
--- a/lib/libhvcall/brokensc1.c
+++ b/lib/libhvcall/brokensc1.c
@@ -36,7 +36,7 @@ static unsigned long hcall(uint32_t inst, unsigned long arg0, unsigned long arg1
 	return r3;
 }
 
-static int check_broken_sc1(void)
+int check_broken_sc1(void)
 {
 	long r;
 
diff --git a/board-qemu/slof/rtas.fs b/board-qemu/slof/rtas.fs
index 092f5b1131f0..1b791b538d92 100644
--- a/board-qemu/slof/rtas.fs
+++ b/board-qemu/slof/rtas.fs
@@ -40,38 +40,10 @@ rtas-cb /rtas-control-block erase
 0 VALUE rtas-entry
 0 VALUE rtas-node
 
-\ Locate qemu RTAS, remove the linux,... properties we really don't
-\ want them to stick around
-
 372 cp
 
 : find-qemu-rtas ( -- )
     " /rtas" find-device get-node to rtas-node
-
-    " linux,rtas-base" rtas-node get-package-property IF
-         device-end EXIT THEN
-    drop l@ to rtas-base
-    " linux,rtas-base" delete-property
-
-    " rtas-size" rtas-node get-package-property IF
-         device-end EXIT THEN
-    drop l@ to rtas-size
-
-    " linux,rtas-entry" rtas-node get-package-property IF
-        rtas-base to rtas-entry
-    ELSE
-        drop l@ to rtas-entry
-        " linux,rtas-entry" delete-property
-    THEN
-
-\    ." RTAS found, base=" rtas-base . ."  size=" rtas-size . cr
-
-    \ Patch the RTAS blob with our sc1 patcher if necessary
-    0
-    rtas-base
-    dup rtas-size +
-    check-and-patch-sc1
-
     device-end
 ;
 find-qemu-rtas
@@ -176,6 +148,14 @@ rtas-node set-node
 : open true ;
 : close ;
 
+: store-hv-rtas-size (  )
+    hv-rtas-size
+    dup to rtas-size
+    encode-int s" rtas-size" s" /rtas" find-node set-property
+;
+
+store-hv-rtas-size
+
 : store-rtas-loc ( adr )
     s" /rtas" find-node >r
     encode-int s" slof,rtas-base" r@ set-property
@@ -184,8 +164,12 @@ rtas-node set-node
 
 : instantiate-rtas ( adr -- entry )
     dup store-rtas-loc
-    dup rtas-base swap rtas-size move
-    rtas-entry rtas-base - +
+    dup to rtas-base
+    dup to rtas-entry
+    s" /rtas" find-node >r
+    dup encode-int s" linux,rtas-base" r@ set-property
+    dup encode-int s" linux,rtas-entry" r> set-property
+    dup hv-instantiate-rtas
 ;
 
 device-end
diff --git a/lib/libhvcall/hvcall.S b/lib/libhvcall/hvcall.S
index 92cf22e4c22c..19163f619be4 100644
--- a/lib/libhvcall/hvcall.S
+++ b/lib/libhvcall/hvcall.S
@@ -127,6 +127,25 @@ ENTRY(hv_cas)
 	HVCALL
 	blr
 
+/* This is the actual RTAS blob copied to the OS at instantiate-rtas */
+ENTRY(hv_rtas)
+	mr	r4,r3
+	lis	r3,KVMPPC_H_RTAS at h
+	ori	r3,r3,KVMPPC_H_RTAS at l
+	HVCALL
+	blr
+	.globl hv_rtas_end
+hv_rtas_end = .;
+
+ENTRY(hv_rtas_broken_sc1)
+	mr	r4,r3
+	lis	r3,KVMPPC_H_RTAS at h
+	ori	r3,r3,KVMPPC_H_RTAS at l
+	.long	0x7c000268
+	blr
+	.globl hv_rtas_broken_sc1_end
+hv_rtas_broken_sc1_end = .;
+
 	.section ".bss"
 inbuf:	.space	16
 inlen:	.space	4
diff --git a/lib/libhvcall/hvcall.code b/lib/libhvcall/hvcall.code
index 5918c901252e..1e47e55a5cc2 100644
--- a/lib/libhvcall/hvcall.code
+++ b/lib/libhvcall/hvcall.code
@@ -128,3 +128,25 @@ PRIM(hv_X2d_update_X2d_dt)
 	unsigned long dt = TOS.u;
 	TOS.u = hv_generic(KVMPPC_H_UPDATE_DT, dt);
 MIRP
+
+PRIM(hv_X2d_instantiate_X2d_rtas)
+	unsigned long start = TOS.u; POP;
+    if (check_broken_sc1()) {
+        memcpy((void *) start, &hv_rtas_broken_sc1,
+                (unsigned long) &hv_rtas_broken_sc1_end -
+                (unsigned long) &hv_rtas_broken_sc1);
+    } else {
+        memcpy((void *) start, &hv_rtas,
+                (unsigned long) &hv_rtas_end - (unsigned long) &hv_rtas);
+    }
+MIRP
+
+PRIM(hv_X2d_rtas_X2d_size)
+    PUSH;
+    if (check_broken_sc1()) {
+        TOS.u = (unsigned long) &hv_rtas_broken_sc1_end -
+                (unsigned long) &hv_rtas_broken_sc1;
+    } else {
+        TOS.u = (unsigned long) &hv_rtas_end - (unsigned long) &hv_rtas;
+    }
+MIRP
diff --git a/lib/libhvcall/hvcall.in b/lib/libhvcall/hvcall.in
index 9193162dd8ce..4165c6bcab58 100644
--- a/lib/libhvcall/hvcall.in
+++ b/lib/libhvcall/hvcall.in
@@ -18,6 +18,8 @@ cod(hv-free-crq)
 cod(hv-send-crq)
 cod(hv-put-tce)
 cod(check-and-patch-sc1)
+cod(hv-instantiate-rtas)
+cod(hv-rtas-size)
 
 cod(RB@)
 cod(RB!)
-- 
2.17.1



More information about the SLOF mailing list