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

Reply via email to