From b3594ec7e0dd3d02043f8da034fe31e9591cd658 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Tue, 5 Apr 2011 20:44:57 +0300 Subject: [PATCH] kvm tools: Separate BIOS specifics into own file Instead of calling various BIOS routines from kvm.c better to have all BIOS specifics sit in bios.c. Signed-off-by: Cyrill Gorcunov Signed-off-by: Pekka Enberg --- bios.c | 48 +++++++++++++++++++++++++++++++++++++ include/kvm/boot-protocol.h | 16 +++++++++++++ include/kvm/e820.h | 2 ++ include/kvm/kvm.h | 2 +- include/kvm/util.h | 2 ++ kvm.c | 48 ++++++++++--------------------------- main.c | 4 +--- 7 files changed, 82 insertions(+), 40 deletions(-) create mode 100644 include/kvm/boot-protocol.h diff --git a/bios.c b/bios.c index 4081769..2199c0c 100644 --- a/bios.c +++ b/bios.c @@ -1,4 +1,6 @@ #include "kvm/kvm.h" +#include "kvm/boot-protocol.h" +#include "kvm/e820.h" #include "kvm/interrupt.h" #include "kvm/util.h" @@ -46,6 +48,49 @@ static void setup_irq_handler(struct kvm *kvm, struct irq_handler *handler) interrupt_table__set(&kvm->interrupt_table, &intr_desc, handler->irq); } +/** + * e820_setup - setup some simple E820 memory map + * @kvm - guest system descriptor + */ +static void e820_setup(struct kvm *kvm) +{ + struct e820_entry *mem_map; + unsigned char *size; + unsigned int i = 0; + + size = guest_flat_to_host(kvm, E820_MAP_SIZE); + mem_map = guest_flat_to_host(kvm, E820_MAP_START); + + *size = E820_MEM_AREAS; + + mem_map[i++] = (struct e820_entry) { + .addr = REAL_MODE_IVT_BEGIN, + .size = EBDA_START - REAL_MODE_IVT_BEGIN, + .type = E820_MEM_USABLE, + }; + mem_map[i++] = (struct e820_entry) { + .addr = EBDA_START, + .size = VGA_RAM_BEGIN - EBDA_START, + .type = E820_MEM_RESERVED, + }; + mem_map[i++] = (struct e820_entry) { + .addr = MB_BIOS_BEGIN, + .size = MB_BIOS_END - MB_BIOS_BEGIN, + .type = E820_MEM_RESERVED, + }; + mem_map[i++] = (struct e820_entry) { + .addr = BZ_KERNEL_START, + .size = kvm->ram_size - BZ_KERNEL_START, + .type = E820_MEM_USABLE, + }; + + BUILD_BUG_ON(i > E820_MEM_AREAS); +} + +/** + * setup_bios - inject BIOS into guest memory + * @kvm - guest system descriptor + */ void setup_bios(struct kvm *kvm) { unsigned long address = MB_BIOS_BEGIN; @@ -73,6 +118,9 @@ void setup_bios(struct kvm *kvm) p = guest_flat_to_host(kvm, MB_BIOS_BEGIN); memcpy(p, bios_rom, bios_rom_size); + /* E820 memory map must be present */ + e820_setup(kvm); + /* * Setup a *fake* real mode vector table, it has only * one real hadler which does just iret diff --git a/include/kvm/boot-protocol.h b/include/kvm/boot-protocol.h new file mode 100644 index 0000000..85b637f --- /dev/null +++ b/include/kvm/boot-protocol.h @@ -0,0 +1,16 @@ +/* + * Linux boot protocol specifics + */ + +#ifndef BOOT_PROTOCOL_H_ +#define BOOT_PROTOCOL_H_ + +/* + * The protected mode kernel part of a modern bzImage is loaded + * at 1 MB by default. + */ +#define BZ_DEFAULT_SETUP_SECTS 4 +#define BZ_KERNEL_START 0x100000UL +#define INITRD_START 0x1000000UL + +#endif /* BOOT_PROTOCOL_H_ */ diff --git a/include/kvm/e820.h b/include/kvm/e820.h index 8cde738..7482eb5 100644 --- a/include/kvm/e820.h +++ b/include/kvm/e820.h @@ -8,6 +8,8 @@ #define E820_MEM_USABLE 1 #define E820_MEM_RESERVED 2 +#define E820_MEM_AREAS 4 + struct e820_entry { uint64_t addr; /* start of memory segment */ uint64_t size; /* size of memory segment */ diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h index 34fcc96..a1af42f 100644 --- a/include/kvm/kvm.h +++ b/include/kvm/kvm.h @@ -41,7 +41,7 @@ void kvm__enable_singlestep(struct kvm *self); bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename, const char *initrd_filename, const char *kernel_cmdline); void kvm__reset_vcpu(struct kvm *self); -void kvm__setup_mem(struct kvm *self); +void kvm__setup_bios(struct kvm *self); void kvm__start_timer(struct kvm *self); void kvm__run(struct kvm *self); void kvm__irq_line(struct kvm *self, int irq, int level); diff --git a/include/kvm/util.h b/include/kvm/util.h index fbc58f9..8c80777 100644 --- a/include/kvm/util.h +++ b/include/kvm/util.h @@ -37,6 +37,8 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))) extern void info(const char *err, ...) __attribute__((format (printf, 1, 2))); extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) + #define DIE_IF(cnd) \ do { \ if (cnd) \ diff --git a/kvm.c b/kvm.c index be0841b..1740e1f 100644 --- a/kvm.c +++ b/kvm.c @@ -2,7 +2,7 @@ #include "kvm/cpufeature.h" #include "kvm/interrupt.h" -#include "kvm/e820.h" +#include "kvm/boot-protocol.h" #include "kvm/util.h" #include @@ -273,13 +273,6 @@ static int load_flat_binary(struct kvm *self, int fd) return true; } -/* - * The protected mode kernel part of a modern bzImage is loaded at 1 MB by - * default. - */ -#define BZ_KERNEL_START 0x100000UL -#define INITRD_START 0x1000000UL -#define BZ_DEFAULT_SETUP_SECTS 4 static const char *BZIMAGE_MAGIC = "HdrS"; static bool load_bzimage(struct kvm *self, int fd_kernel, @@ -571,36 +564,19 @@ void kvm__reset_vcpu(struct kvm *self) kvm__setup_msrs(self); } -void kvm__setup_mem(struct kvm *self) +/** + * kvm__setup_bios - inject BIOS into guest system memory + * @self - guest system descriptor + * + * This function is a main routine where we poke guest memory + * and install BIOS there. + */ +void kvm__setup_bios(struct kvm *self) { - struct e820_entry *mem_map; - unsigned char *size; + /* standart minimal configuration */ + setup_bios(self); - size = guest_flat_to_host(self, E820_MAP_SIZE); - mem_map = guest_flat_to_host(self, E820_MAP_START); - - *size = 4; - - mem_map[0] = (struct e820_entry) { - .addr = REAL_MODE_IVT_BEGIN, - .size = EBDA_START - REAL_MODE_IVT_BEGIN, - .type = E820_MEM_USABLE, - }; - mem_map[1] = (struct e820_entry) { - .addr = EBDA_START, - .size = VGA_RAM_BEGIN - EBDA_START, - .type = E820_MEM_RESERVED, - }; - mem_map[2] = (struct e820_entry) { - .addr = MB_BIOS_BEGIN, - .size = MB_BIOS_END - MB_BIOS_BEGIN, - .type = E820_MEM_RESERVED, - }; - mem_map[3] = (struct e820_entry) { - .addr = BZ_KERNEL_START, - .size = self->ram_size - BZ_KERNEL_START, - .type = E820_MEM_USABLE, - }; + /* FIXME: SMP, ACPI and friends here */ } #define TIMER_INTERVAL_NS 1000000 /* 1 msec */ diff --git a/main.c b/main.c index f755804..1eeb311 100644 --- a/main.c +++ b/main.c @@ -162,9 +162,7 @@ int main(int argc, char *argv[]) kvm__reset_vcpu(kvm); - setup_bios(kvm); - - kvm__setup_mem(kvm); + kvm__setup_bios(kvm); if (single_step) kvm__enable_singlestep(kvm);