This patch mmaps guest kernel into it's own memory slot instead of reading it into the memory. The advantages are: - Smaller memory footprint (same effect as KSM if running multiple guests) - Faster loading of larger kernels. Suggested-by: "Sweeney, Andrew John" <ajsween@xxxxxxxxxx> Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> --- tools/kvm/x86/include/kvm/kvm-arch.h | 4 ++ tools/kvm/x86/kvm.c | 60 +++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/tools/kvm/x86/include/kvm/kvm-arch.h b/tools/kvm/x86/include/kvm/kvm-arch.h index 686b1b8..3f7a311 100644 --- a/tools/kvm/x86/include/kvm/kvm-arch.h +++ b/tools/kvm/x86/include/kvm/kvm-arch.h @@ -35,6 +35,10 @@ struct kvm { u64 ram_size; void *ram_start; + int bz_fd; + void *bz_start; + u32 bz_len; + bool nmi_disabled; bool single_step; diff --git a/tools/kvm/x86/kvm.c b/tools/kvm/x86/kvm.c index da4a6b6..42d7810 100644 --- a/tools/kvm/x86/kvm.c +++ b/tools/kvm/x86/kvm.c @@ -9,6 +9,7 @@ #include <asm/bootparam.h> #include <linux/kvm.h> +#include <linux/kernel.h> #include <sys/types.h> #include <sys/ioctl.h> @@ -93,24 +94,51 @@ void kvm__init_ram(struct kvm *kvm) void *host_mem; if (kvm->ram_size < KVM_32BIT_GAP_START) { - /* Use a single block of RAM for 32bit RAM */ - + /* Memory between 0 and where the kernel starts */ + u64 bzl = ALIGN(kvm->bz_len, PAGE_SIZE); phys_start = 0; - phys_size = kvm->ram_size; + phys_size = BZ_KERNEL_START; host_mem = kvm->ram_start; kvm__register_mem(kvm, phys_start, phys_size, host_mem); - } else { - /* First RAM range from zero to the PCI gap: */ + /* Mapped kernel */ + phys_start = BZ_KERNEL_START; + phys_size = bzl; + host_mem = kvm->bz_start; + + kvm__register_mem(kvm, phys_start, phys_size, host_mem); + + /* Rest of the memory */ + phys_start = BZ_KERNEL_START + bzl; + phys_size = kvm->ram_size - (BZ_KERNEL_START + bzl); + host_mem = kvm->ram_start + (BZ_KERNEL_START + bzl); + + kvm__register_mem(kvm, phys_start, phys_size, host_mem); + } else { + /* Memory between 0 and where the kernel starts */ + u64 bzl = ALIGN(kvm->bz_len, PAGE_SIZE); phys_start = 0; - phys_size = KVM_32BIT_GAP_START; + phys_size = BZ_KERNEL_START; host_mem = kvm->ram_start; kvm__register_mem(kvm, phys_start, phys_size, host_mem); - /* Second RAM range from 4GB to the end of RAM: */ + /* Mapped kernel */ + phys_start = BZ_KERNEL_START; + phys_size = bzl; + host_mem = kvm->bz_start; + kvm__register_mem(kvm, phys_start, phys_size, host_mem); + + /* Rest of the memory until the 4GB gap */ + phys_start = BZ_KERNEL_START + bzl; + phys_size = KVM_32BIT_GAP_START - (BZ_KERNEL_START + bzl); + host_mem = kvm->ram_start + (BZ_KERNEL_START + bzl); + + kvm__register_mem(kvm, phys_start, phys_size, host_mem); + + /* RAM range from 4GB to the end of RAM */ phys_start = 0x100000000ULL; phys_size = kvm->ram_size - phys_size; host_mem = kvm->ram_start + phys_start; @@ -232,7 +260,8 @@ bool load_bzimage(struct kvm *kvm, int fd_kernel, struct boot_params *kern_boot; unsigned long setup_sects; struct boot_params boot; - size_t cmdline_size; + struct stat st; + size_t cmdline_size, setup_end; ssize_t setup_size; void *p; int nr; @@ -242,6 +271,9 @@ bool load_bzimage(struct kvm *kvm, int fd_kernel, * memory layout. */ + if (fstat(fd_kernel, &st) < 0) + die_perror("fstat"); + if (lseek(fd_kernel, 0, SEEK_SET) < 0) die_perror("lseek"); @@ -268,11 +300,15 @@ bool load_bzimage(struct kvm *kvm, int fd_kernel, if (read(fd_kernel, p, setup_size) != setup_size) die_perror("read"); - /* copy vmlinux.bin to BZ_KERNEL_START*/ - p = guest_flat_to_host(kvm, BZ_KERNEL_START); + /* mmap the actual kernel */ + kvm->bz_fd = dup(fd_kernel); + kvm->bz_len = st.st_size; + setup_end = ALIGN(setup_size - PAGE_SIZE, PAGE_SIZE); /* Need it aligned to PAGE_SIZE */ + kvm->bz_start = mmap(NULL, kvm->bz_len, PROT_READ | PROT_WRITE, + MAP_PRIVATE, kvm->bz_fd, setup_end); - while ((nr = read(fd_kernel, p, 65536)) > 0) - p += nr; + /* NOP everything before the kernel start */ + memset(kvm->bz_start, 0x90, setup_size - setup_end); p = guest_flat_to_host(kvm, BOOT_CMDLINE_OFFSET); if (kernel_cmdline) { -- 1.7.8 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html