On 25 Feb 2012, at 02:23, Anthony Liguori <[email protected]> wrote:
> On 02/24/2012 09:05 AM, Pekka Enberg wrote: >> 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. > > You may want to call it firmware as other platforms also have firmware. For > instance, it may be desirable to use the same interface to load SLOF with > spapr. Seconded, "BIOS" is a bit of an arch-specific phrase... and antique ;) Matt > >> >> Cc: Yang Bai<[email protected]> >> Cc: Matt Evans<[email protected]> >> Cc: Ron Minnich<[email protected]> >> Cc: Anthony Liguori<[email protected]> >> Cc: John Floren<[email protected]> >> Cc: Sasha Levin<[email protected]> >> Cc: Cyrill Gorcunov<[email protected]> >> Cc: Asias He<[email protected]> >> Cc: Ingo Molnar<[email protected]> >> Signed-off-by: Pekka Enberg<[email protected]> >> --- >> 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 > > FYI, this will work with SeaBIOS because it's currently 128k. But the normal > thing is to load the last 128k of the BIOS ROM at 1MB - 128k, with the full > ROM mapped at 4GB - sizeof(ROM). > > SeaBIOS certainly expects the ROM to be located in both places. > > Also note that the area at 1MB - 128k is special. There's two distinct > regions mapped here, normal RAM and then the BIOS ROM. Depending on the > settings of the PAM registers, a guest can chose to see either piece of > memory. In fact, it can control read and write access independently such > that writes go to RAM and reads come from the BIOS area. > > This is used to implement shadowing. SeaBIOS does special case this under > KVM since it's not possible to execute out of MMIO under KVM. > > Regards, > > Anthony Liguori -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
