This patch adds a "--bios" command line option to "vm run". You can use this to try to boot with SeaBIOS, for example: ./vm run --bios=/usr/share/seabios/bios.bin \ --disk $HOME/images/debian_lenny_amd64_standard.qcow2 This doesn't boot yet for obvious reasons but at least people can now start to play with external BIOS images easily. Cc: Yang Bai <hamo.by@xxxxxxxxx> Cc: Matt Evans <matt@xxxxxxxxxx> Cc: Ron Minnich <rminnich@xxxxxxxxx> Cc: Anthony Liguori <aliguori@xxxxxxxxxx> Cc: John Floren <john@xxxxxxxxxxx> Cc: Sasha Levin <levinsasha928@xxxxxxxxx> Cc: Cyrill Gorcunov <gorcunov@xxxxxxxxxx> Cc: Asias He <asias.hejun@xxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxx> Signed-off-by: Pekka Enberg <penberg@xxxxxxxxxx> --- tools/kvm/Makefile | 2 + tools/kvm/builtin-run.c | 32 +++++++++++++++++++---------- tools/kvm/include/kvm/kvm.h | 1 + tools/kvm/powerpc/boot.c | 8 +++++++ tools/kvm/x86/boot.c | 41 ++++++++++++++++++++++++++++++++++++++ tools/kvm/x86/include/kvm/bios.h | 3 +- 6 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 tools/kvm/powerpc/boot.c create mode 100644 tools/kvm/x86/boot.c diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index cfa5547..0a9c2cc 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -113,6 +113,7 @@ LIBFDT_OBJS = $(patsubst %,../../scripts/dtc/libfdt/%,$(LIBFDT_SRC)) #x86 ifeq ($(ARCH),x86) DEFINES += -DCONFIG_X86 + OBJS += x86/boot.o OBJS += x86/cpuid.o OBJS += x86/interrupt.o OBJS += x86/ioport.o @@ -129,6 +130,7 @@ endif # POWER/ppc: Actually only support ppc64 currently. ifeq ($(uname_M), ppc64) DEFINES += -DCONFIG_PPC + OBJS += powerpc/boot.o OBJS += powerpc/ioport.o OBJS += powerpc/irq.o OBJS += powerpc/kvm.o diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c index 466169e..f96c581 100644 --- a/tools/kvm/builtin-run.c +++ b/tools/kvm/builtin-run.c @@ -76,6 +76,7 @@ static const char *kernel_cmdline; static const char *kernel_filename; static const char *vmlinux_filename; static const char *initrd_filename; +static const char *bios_filename; static const char *image_filename[MAX_DISK_IMAGES]; static const char *console; static const char *dev; @@ -458,6 +459,8 @@ static const struct option options[] = { "Initial RAM disk image"), OPT_STRING('p', "params", &kernel_cmdline, "params", "Kernel command line arguments"), + OPT_STRING('b', "bios", &bios_filename, "bios", + "BIOS to boot in virtual machine"), OPT_GROUP("Networking options:"), OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params", @@ -1110,14 +1113,16 @@ static int kvm_cmd_run_init(int argc, const char **argv) printf(" # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME, kernel_filename, ram_size / 1024 / 1024, nrcpus, guest_name); - if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename, - real_cmdline, vidmode)) - die("unable to load kernel %s", kernel_filename); + if (!bios_filename) { + if (!kvm__load_kernel(kvm, kernel_filename, + initrd_filename, real_cmdline, vidmode)) + die("unable to load kernel %s", kernel_filename); - kvm->vmlinux = vmlinux_filename; - r = symbol_init(kvm); - if (r < 0) - pr_debug("symbol_init() failed with error %d\n", r); + kvm->vmlinux = vmlinux_filename; + r = symbol_init(kvm); + if (r < 0) + pr_debug("symbol_init() failed with error %d\n", r); + } ioport__setup_arch(); @@ -1218,10 +1223,15 @@ static int kvm_cmd_run_init(int argc, const char **argv) kvm__start_timer(kvm); - kvm__arch_setup_firmware(kvm); - if (r < 0) { - pr_err("kvm__arch_setup_firmware() failed with error %d\n", r); - goto fail; + if (bios_filename) { + if (!kvm__load_bios(kvm, bios_filename)) + die("unable to load bios %s: %s", bios_filename, strerror(errno)); + } else { + kvm__arch_setup_firmware(kvm); + if (r < 0) { + pr_err("kvm__arch_setup_firmware() failed with error %d\n", r); + goto fail; + } } for (i = 0; i < nrcpus; i++) { diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h index 7870118..258d11a 100644 --- a/tools/kvm/include/kvm/kvm.h +++ b/tools/kvm/include/kvm/kvm.h @@ -39,6 +39,7 @@ int kvm__recommended_cpus(struct kvm *kvm); int kvm__max_cpus(struct kvm *kvm); void kvm__init_ram(struct kvm *kvm); int kvm__exit(struct kvm *kvm); +bool kvm__load_bios(struct kvm *kvm, const char *bios_filename); bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename, const char *initrd_filename, const char *kernel_cmdline, u16 vidmode); void kvm__start_timer(struct kvm *kvm); diff --git a/tools/kvm/powerpc/boot.c b/tools/kvm/powerpc/boot.c new file mode 100644 index 0000000..8c99831 --- /dev/null +++ b/tools/kvm/powerpc/boot.c @@ -0,0 +1,8 @@ +#include "kvm/kvm.h" + +#include <stdbool.h> + +bool kvm__load_bios(struct kvm *kvm, const char *bios_filename) +{ + return false; +} diff --git a/tools/kvm/x86/boot.c b/tools/kvm/x86/boot.c new file mode 100644 index 0000000..383d9f7 --- /dev/null +++ b/tools/kvm/x86/boot.c @@ -0,0 +1,41 @@ +#include "kvm/kvm.h" + +#include "kvm/util.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdbool.h> +#include <fcntl.h> + +#define BIOS_SELECTOR 0xf000 +#define BIOS_IP 0xfff0 +#define BIOS_SP 0x8000 + +bool kvm__load_bios(struct kvm *kvm, const char *bios_filename) +{ + struct stat st; + void *p; + int fd; + int nr; + + fd = open(bios_filename, O_RDONLY); + if (fd < 0) + return false; + + if (fstat(fd, &st)) + return false; + + if (st.st_size > MB_BIOS_SIZE) + die("BIOS image %s is too big to fit in memory (%lu KB).\n", bios_filename, st.st_size / 1024); + + p = guest_flat_to_host(kvm, MB_BIOS_BEGIN); + + while ((nr = read(fd, p, st.st_size)) > 0) + p += nr; + + kvm->boot_selector = BIOS_SELECTOR; + kvm->boot_ip = BIOS_IP; + kvm->boot_sp = BIOS_SP; + + return true; +} diff --git a/tools/kvm/x86/include/kvm/bios.h b/tools/kvm/x86/include/kvm/bios.h index de569bc..9d677ae 100644 --- a/tools/kvm/x86/include/kvm/bios.h +++ b/tools/kvm/x86/include/kvm/bios.h @@ -26,8 +26,9 @@ #define E820_MAP_START EBDA_START -#define MB_BIOS_BEGIN 0x000f0000 +#define MB_BIOS_BEGIN 0x000e0000 #define MB_BIOS_END 0x000fffff +#define MB_BIOS_SIZE (MB_BIOS_END - MB_BIOS_BEGIN + 1) #define VGA_RAM_BEGIN 0x000a0000 #define VGA_RAM_END 0x000bffff -- 1.7.6.5 -- 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