From 3d359d405befcadca924545446004c441ebf05c2 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 27 Mar 2010 10:53:15 +0200 Subject: [PATCH] kvm: Hardcode a "reset vector" at f000:fff0 It seems that if we attempt to run code at any other location than f000:fff0, we get an KVM_EXIT_UNKNOWN error. To work around that, hardcode a "reset vector" at f000:fff0 that jumps to 0000:0x7c000 and load the kernel at the latter location. Signed-off-by: Pekka Enberg --- tools/kvm/kvm.c | 31 +++++++++++++++++++++++++------ tools/kvm/util.h | 2 ++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c index b5a20b68b42f..5b241137cc23 100644 --- a/tools/kvm/kvm.c +++ b/tools/kvm/kvm.c @@ -153,8 +153,13 @@ static inline uint32_t segment_to_flat(uint16_t selector, uint16_t offset) return ((uint32_t)selector << 4) + (uint32_t) offset; } -#define BIN_BOOT_LOADER_CS 0xf000 -#define BIN_BOOT_LOADER_IP 0xfff0 +#define RESET_CS 0xf000 +#define RESET_IP 0xfff0 + +#define BIN_BOOT_LOADER_CS 0x0000 +#define BIN_BOOT_LOADER_IP 0x7c00 + +static unsigned char reset_code[] = { 0xea, 0x00, 0x7c, 0x00, 0x00 }; static int load_flat_binary(struct kvm *kvm, int fd) { @@ -169,8 +174,12 @@ static int load_flat_binary(struct kvm *kvm, int fd) while ((nr = read(fd, p, 65536)) > 0) p += nr; - kvm->boot_cs = BIN_BOOT_LOADER_CS; - kvm->boot_ip = BIN_BOOT_LOADER_IP; + p = guest_addr_to_host(kvm, segment_to_flat(RESET_CS, RESET_IP)); + + memcpy(p, reset_code, ARRAY_SIZE(reset_code)); + + kvm->boot_cs = RESET_CS; + kvm->boot_ip = RESET_IP; return true; } @@ -230,8 +239,12 @@ static bool load_bzimage(struct kvm *kvm, int fd) while ((nr = read(fd, p, 65536)) > 0) p += nr; - kvm->boot_cs = 0; - kvm->boot_ip = BZ_BOOT_LOADER_START; + p = guest_addr_to_host(kvm, segment_to_flat(RESET_CS, RESET_IP)); + + memcpy(p, reset_code, ARRAY_SIZE(reset_code)); + + kvm->boot_cs = RESET_CS; + kvm->boot_ip = RESET_IP; return true; } @@ -457,6 +470,12 @@ void kvm__show_code(struct kvm *self) unsigned int i; uint8_t *ip; + if (ioctl(self->vcpu_fd, KVM_GET_REGS, &self->regs) < 0) + die("KVM_GET_REGS failed"); + + if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &self->sregs) < 0) + die("KVM_GET_SREGS failed"); + ip = guest_addr_to_host(self, ip_real_to_flat(self, self->regs.rip) - code_prologue); printf("Code: "); diff --git a/tools/kvm/util.h b/tools/kvm/util.h index ddb276871c4f..fa91b95cb056 100644 --- a/tools/kvm/util.h +++ b/tools/kvm/util.h @@ -1,6 +1,8 @@ #ifndef UTIL_H_ #define UTIL_H_ +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + /* * Some bits are stolen from perf tool :) */ -- 2.39.5