diff mbox

[4/4] pre_init: add ARM implementations

Message ID 1456327988-31568-5-git-send-email-andre.przywara@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Andre Przywara Feb. 24, 2016, 3:33 p.m. UTC
The pre_init stub consists of two syscalls mouting the host's FS
via 9pfs and then calling the actual init binary, which can now
use normal dynamic linking.
Based on the x86 code provide an ARM and ARM64 implementation of
that. Beside removing the need for static linkage it reduces the
size of the kvmtool binary by quite a lot (numbers for aarch64):

-rwxr-xr-x 1 root root     9952 Nov 16 14:37 guest/init
-rwxr-xr-x 1 root root      512 Nov 16 14:37 guest/pre_init
-rwxr-xr-x 2 root root  1284704 Nov 16 14:37 lkvm
vs. the old version:
-rwxr-xr-x 1 root root   776024 Nov 16 14:38 guest/init
-rwxr-xr-x 2 root root  2050112 Nov 16 14:38 lkvm

Tested on Midway and Juno.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 Makefile           |  2 ++
 arm/aarch32/init.S | 44 ++++++++++++++++++++++++++++++++++++++++++++
 arm/aarch64/init.S | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 90 insertions(+)
 create mode 100644 arm/aarch32/init.S
 create mode 100644 arm/aarch64/init.S

Comments

Will Deacon March 2, 2016, 3 a.m. UTC | #1
On Wed, Feb 24, 2016 at 03:33:08PM +0000, Andre Przywara wrote:
> The pre_init stub consists of two syscalls mouting the host's FS
> via 9pfs and then calling the actual init binary, which can now
> use normal dynamic linking.
> Based on the x86 code provide an ARM and ARM64 implementation of
> that. Beside removing the need for static linkage it reduces the
> size of the kvmtool binary by quite a lot (numbers for aarch64):
> 
> -rwxr-xr-x 1 root root     9952 Nov 16 14:37 guest/init
> -rwxr-xr-x 1 root root      512 Nov 16 14:37 guest/pre_init
> -rwxr-xr-x 2 root root  1284704 Nov 16 14:37 lkvm
> vs. the old version:
> -rwxr-xr-x 1 root root   776024 Nov 16 14:38 guest/init
> -rwxr-xr-x 2 root root  2050112 Nov 16 14:38 lkvm
> 
> Tested on Midway and Juno.

Hmm, I'm not super keen on switching behaviour like this on arm, where
it's not uncommon to build a static lkvm and transfer it to a remote
target and expect init to work.

Perhaps we could only do this when building a dynamic executable?

Will
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andre Przywara March 2, 2016, 11:38 p.m. UTC | #2
Hi,

On 02/03/16 03:00, Will Deacon wrote:
> On Wed, Feb 24, 2016 at 03:33:08PM +0000, Andre Przywara wrote:
>> The pre_init stub consists of two syscalls mouting the host's FS
>> via 9pfs and then calling the actual init binary, which can now
>> use normal dynamic linking.
>> Based on the x86 code provide an ARM and ARM64 implementation of
>> that. Beside removing the need for static linkage it reduces the
>> size of the kvmtool binary by quite a lot (numbers for aarch64):
>>
>> -rwxr-xr-x 1 root root     9952 Nov 16 14:37 guest/init
>> -rwxr-xr-x 1 root root      512 Nov 16 14:37 guest/pre_init
>> -rwxr-xr-x 2 root root  1284704 Nov 16 14:37 lkvm
>> vs. the old version:
>> -rwxr-xr-x 1 root root   776024 Nov 16 14:38 guest/init
>> -rwxr-xr-x 2 root root  2050112 Nov 16 14:38 lkvm
>>
>> Tested on Midway and Juno.
> 
> Hmm, I'm not super keen on switching behaviour like this on arm, where
> it's not uncommon to build a static lkvm and transfer it to a remote
> target and expect init to work.

So are you concerned about a fully static root file system on the host,
which does not provide libc.so and/or ld-linux.so at all? Is that really
a use case? I had the impression that people use a statically linked
kvmtool to avoid dependencies like to libfdt.so.
In this case I am wondering if we should provide some switch to build a
static lkvm with a static init if people are concerned, or we should
ship a guest/init binary statically linked against musl libc, for
instance: this is only 29K compared to the above multi-100 KB gcc version.
Or is there some trick to build small static binaries linked against glibc?
Actually by just looking at init.c: Should we code the whole of it in
assembly? Apart from printf it only consists of syscalls.

> Perhaps we could only do this when building a dynamic executable?

This is of course an option as well.

Cheers,
Andre

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Will Deacon March 3, 2016, 9:08 p.m. UTC | #3
On Wed, Mar 02, 2016 at 11:38:34PM +0000, André Przywara wrote:
> On 02/03/16 03:00, Will Deacon wrote:
> > On Wed, Feb 24, 2016 at 03:33:08PM +0000, Andre Przywara wrote:
> >> The pre_init stub consists of two syscalls mouting the host's FS
> >> via 9pfs and then calling the actual init binary, which can now
> >> use normal dynamic linking.
> >> Based on the x86 code provide an ARM and ARM64 implementation of
> >> that. Beside removing the need for static linkage it reduces the
> >> size of the kvmtool binary by quite a lot (numbers for aarch64):
> >>
> >> -rwxr-xr-x 1 root root     9952 Nov 16 14:37 guest/init
> >> -rwxr-xr-x 1 root root      512 Nov 16 14:37 guest/pre_init
> >> -rwxr-xr-x 2 root root  1284704 Nov 16 14:37 lkvm
> >> vs. the old version:
> >> -rwxr-xr-x 1 root root   776024 Nov 16 14:38 guest/init
> >> -rwxr-xr-x 2 root root  2050112 Nov 16 14:38 lkvm
> >>
> >> Tested on Midway and Juno.
> > 
> > Hmm, I'm not super keen on switching behaviour like this on arm, where
> > it's not uncommon to build a static lkvm and transfer it to a remote
> > target and expect init to work.
> 
> So are you concerned about a fully static root file system on the host,
> which does not provide libc.so and/or ld-linux.so at all? Is that really
> a use case? I had the impression that people use a statically linked
> kvmtool to avoid dependencies like to libfdt.so.

Right. There are certainly environments where kvmtool is used that don't
have a dynanmic linker, and I'd really like lkvm-static to work there.

> > Perhaps we could only do this when building a dynamic executable?
> 
> This is of course an option as well.

I think it's the right thing to do.

Will
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Makefile b/Makefile
index 54bdd31..57b0bdd 100644
--- a/Makefile
+++ b/Makefile
@@ -161,6 +161,7 @@  ifeq ($(ARCH), arm)
 	OBJS		+= $(OBJS_ARM_COMMON)
 	OBJS		+= arm/aarch32/arm-cpu.o
 	OBJS		+= arm/aarch32/kvm-cpu.o
+	ARCH_PRE_INIT	=  arm/aarch32/init.S
 	ARCH_INCLUDE	:= $(HDRS_ARM_COMMON)
 	ARCH_INCLUDE	+= -Iarm/aarch32/include
 	CFLAGS		+= -march=armv7-a
@@ -174,6 +175,7 @@  ifeq ($(ARCH), arm64)
 	OBJS		+= $(OBJS_ARM_COMMON)
 	OBJS		+= arm/aarch64/arm-cpu.o
 	OBJS		+= arm/aarch64/kvm-cpu.o
+	ARCH_PRE_INIT	=  arm/aarch64/init.S
 	ARCH_INCLUDE	:= $(HDRS_ARM_COMMON)
 	ARCH_INCLUDE	+= -Iarm/aarch64/include
 
diff --git a/arm/aarch32/init.S b/arm/aarch32/init.S
new file mode 100644
index 0000000..c023195
--- /dev/null
+++ b/arm/aarch32/init.S
@@ -0,0 +1,44 @@ 
+/*
+ * #!/bin/sh
+ * mount -t 9p -o trans=virtio,version=9p2000.L hostfs /host
+ * /virt/init $*
+ */
+
+#include <asm/unistd.h>
+
+.text
+.globl _start
+_start:
+
+	mov	r7, #__NR_mount
+	ldr	r0, =.m_dev
+	ldr	r1, =.m_dir
+	ldr	r2, =.m_typ
+	mov	r3, #1			// MS_RDONLY
+	ldr	r4, =.m_opt
+	svc	#0
+
+	mov	r7, #__NR_execve
+	ldr	r0, =.e_nam		// 1st arg: filename
+	add	r1, sp, #4		// 2nd arg: argv[0]
+	str	r0, [r1]		// change argv[0]
+	ldr	r2, [sp]
+	add	r2, r2, #1		// r2 = argc + 1
+	add	r2, r1, r2, lsl #2	// 3rd arg: envp = argv[0] + argc + 1
+	svc	#0
+
+	mov	r7, #__NR_exit
+	mov	r0, #1
+	svc	#0			// panic
+
+.m_dev:
+.string "hostfs"
+.m_dir:
+.string "/host"
+.m_typ:
+.string "9p"
+.m_opt:
+.string "trans=virtio,version=9p2000.L"
+
+.e_nam:
+.string "/virt/init"
diff --git a/arm/aarch64/init.S b/arm/aarch64/init.S
new file mode 100644
index 0000000..567bf97
--- /dev/null
+++ b/arm/aarch64/init.S
@@ -0,0 +1,44 @@ 
+/*
+ * #!/bin/sh
+ * mount -t 9p -o trans=virtio,version=9p2000.L hostfs /host
+ * /virt/init $*
+ */
+
+#include <asm/unistd.h>
+
+.text
+.globl _start
+_start:
+
+	mov	x8, #__NR_mount
+	ldr	x0, =.m_dev
+	ldr	x1, =.m_dir
+	ldr	x2, =.m_typ
+	mov	x3, #1			// MS_RDONLY
+	ldr	x4, =.m_opt
+	svc	#0
+
+	mov	x8, #__NR_execve
+	ldr	x0, =.e_nam		// 1st arg: filename
+	add	x1, sp, #8		// 2nd arg: argv (passed through)
+	str	x0, [x1]		// change argv[0] to contain filename
+	ldr	x2, [sp]
+	add	x2, x2, #1		// x2 = argc + 1
+	add	x2, x1, x2, lsl #3	// 3rd arg: envp = argv[0] + argc + 1
+	svc	#0
+
+	mov	x8, #__NR_exit
+	mov	x0, #1
+	svc	#0			// panic
+
+.m_dev:
+.string "hostfs"
+.m_dir:
+.string "/host"
+.m_typ:
+.string "9p"
+.m_opt:
+.string "trans=virtio,version=9p2000.L"
+
+.e_nam:
+.string "/virt/init"