kvmtool/x86: implement guest_pre_init

Add the tiny x86/init.S which just mounts /host and execs
/virt/init.

NOTE: of course, the usage of CONFIG_GUEST_PRE_INIT is ugly, we
need to cleanup this code. But I'd prefer to do this on top of
this minimal/simple change. And I think this needs cleanups in
any case, for example I think lkvm shouldn't abuse the "init="
kernel parameter at all.

Acked-by: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
Oleg Nesterov
2015-10-19 12:59:48 +02:00
committed by Will Deacon
parent 0f04bdf429
commit 5614f9d933
5 changed files with 58 additions and 1 deletions

View File

@@ -110,6 +110,7 @@ endif
ifeq ($(ARCH),x86_64)
ARCH := x86
DEFINES += -DCONFIG_X86_64
ARCH_PRE_INIT = x86/init.S
endif
### Arch-specific stuff

View File

@@ -594,7 +594,11 @@ static struct kvm *kvm_cmd_run_init(int argc, const char **argv)
if (kvm->cfg.custom_rootfs) {
kvm_run_set_sandbox(kvm);
#ifdef CONFIG_GUEST_PRE_INIT
strcat(real_cmdline, " init=/virt/pre_init");
#else
strcat(real_cmdline, " init=/virt/init");
#endif
if (!kvm->cfg.no_dhcp)
strcat(real_cmdline, " ip=dhcp");

View File

@@ -144,12 +144,24 @@ static int extract_file(const char *guestfs_name, const char *filename,
extern char _binary_guest_init_start;
extern char _binary_guest_init_size;
extern char _binary_guest_pre_init_start;
extern char _binary_guest_pre_init_size;
int kvm_setup_guest_init(const char *guestfs_name)
{
return extract_file(guestfs_name, "virt/init",
int err;
#ifdef CONFIG_GUEST_PRE_INIT
err = extract_file(guestfs_name, "virt/pre_init",
&_binary_guest_pre_init_start,
&_binary_guest_pre_init_size);
if (err)
return err;
#endif
err = extract_file(guestfs_name, "virt/init",
&_binary_guest_init_start,
&_binary_guest_init_size);
return err;
}
#else
int kvm_setup_guest_init(const char *guestfs_name)

View File

@@ -30,7 +30,9 @@ static int run_process_sandbox(char *filename)
static void do_mounts(void)
{
#ifndef CONFIG_GUEST_PRE_INIT
mount("hostfs", "/host", "9p", MS_RDONLY, "trans=virtio,version=9p2000.L");
#endif
mount("", "/sys", "sysfs", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);

38
x86/init.S Normal file
View File

@@ -0,0 +1,38 @@
.data
.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"
.text
.globl _start
_start:
mov $165, %rax # __NR_mount
mov $.m_dev, %rdi
mov $.m_dir, %rsi
mov $.m_typ, %rdx
mov $1, %r10 # MS_RDONLY
mov $.m_opt, %r8
syscall
mov $59, %rax # __NR_execve
mov $.e_nam, %rdi
lea 8(%rsp), %rsi # argv[]
mov %rdi, (%rsi) # change argv[0]
pop %rcx # argc
inc %rcx
lea (%rsi,%rcx,8), %rdx # envp[]
syscall
mov $60, %rax # __NR_exit
mov $1, %rdi
syscall # panic