]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Separate KVM code from the main loop
authorPekka Enberg <penberg@cs.helsinki.fi>
Thu, 25 Mar 2010 15:40:51 +0000 (17:40 +0200)
committerPekka Enberg <penberg@cs.helsinki.fi>
Thu, 25 Mar 2010 15:40:51 +0000 (17:40 +0200)
This patch separates the KVM code in its own file and cleans everything up a
bit while at it.

Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
tools/kvm/Makefile
tools/kvm/include/kvm/kvm.h [new file with mode: 0644]
tools/kvm/kvm.c
tools/kvm/main.c [new file with mode: 0644]

index 3db5fc4c610b88aa8c60a6d469302c6c26eec3e3..0bc48915fa569fb9271b3730770c21ecf02d18e1 100644 (file)
@@ -1,11 +1,30 @@
 PROGRAM        = kvm
 
-OBJS   += kvm.o
 OBJS   += cpu.o
+OBJS   += kvm.o
+OBJS   += main.o
 OBJS   += util.o
 
 CFLAGS += -Iinclude
 
+WARNINGS += -Wall
+WARNINGS += -Wcast-align
+WARNINGS += -Wformat=2
+WARNINGS += -Winit-self
+WARNINGS += -Wmissing-declarations
+WARNINGS += -Wmissing-prototypes
+WARNINGS += -Wnested-externs
+WARNINGS += -Wno-system-headers
+WARNINGS += -Wold-style-definition
+WARNINGS += -Wredundant-decls
+WARNINGS += -Wsign-compare
+WARNINGS += -Wstrict-prototypes
+WARNINGS += -Wundef
+WARNINGS += -Wvolatile-register-var
+WARNINGS += -Wwrite-strings
+
+CFLAGS += $(WARNINGS)
+
 all: $(PROGRAM)
 
 $(PROGRAM): $(OBJS)
diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
new file mode 100644 (file)
index 0000000..6f8d4b0
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef KVM__KVM_H
+#define KVM__KVM_H
+
+#include <linux/kvm.h> /* for struct kvm_regs */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+struct kvm {
+       int                     sys_fd;         /* For system ioctls(), i.e. /dev/kvm */
+       int                     vm_fd;          /* For VM ioctls() */
+       int                     vcpu_fd;        /* For VCPU ioctls() */
+       struct kvm_run          *kvm_run;
+
+       uint64_t                ram_size;
+       void                    *ram_start;
+
+       struct kvm_regs         regs;
+};
+
+struct kvm *kvm__init(void);
+void kvm__enable_singlestep(struct kvm *self);
+uint32_t kvm__load_kernel(struct kvm *kvm, const char *kernel_filename);
+void kvm__reset_vcpu(struct kvm *self, uint64_t rip);
+void kvm__run(struct kvm *self);
+void kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int direction, int size, uint32_t count);
+
+/*
+ * Debugging
+ */
+void kvm__show_code(struct kvm *self);
+void kvm__show_registers(struct kvm *self);
+
+extern const char *kvm_exit_reasons[];
+
+#endif /* KVM__KVM_H */
index c8bb938d4bf929172f0c94078a798e172a7cc744..0848d3f1be785ffa780666a420501722f0fff074 100644 (file)
@@ -1,7 +1,10 @@
+#include "kvm/kvm.h"
+
 #include <linux/kvm.h>
 
 #include <asm/bootparam.h>
 
+#include <sys/ioctl.h>
 #include <inttypes.h>
 #include <sys/mman.h>
 #include <stdbool.h>
 # define KVM_EXIT_INTERNAL_ERROR               17
 #endif
 
-struct kvm {
-       int                     sys_fd;         /* For system ioctls(), i.e. /dev/kvm */
-       int                     vm_fd;          /* For VM ioctls() */
-       int                     vcpu_fd;        /* For VCPU ioctls() */
-       struct kvm_run          *kvm_run;
-
-       uint64_t                ram_size;
-       void                    *ram_start;
+#define DEFINE_KVM_EXIT_REASON(reason) [reason] = #reason
 
-       struct kvm_regs         regs;
+const char *kvm_exit_reasons[] = {
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_UNKNOWN),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_EXCEPTION),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_IO),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_HYPERCALL),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_DEBUG),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_HLT),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_MMIO),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_IRQ_WINDOW_OPEN),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_SHUTDOWN),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_FAIL_ENTRY),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTR),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_SET_TPR),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_TPR_ACCESS),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_SIEIC),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_RESET),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_DCR),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_NMI),
+       DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTERNAL_ERROR),
 };
 
-static inline bool kvm__supports_extension(struct kvm *self, unsigned int extension)
+static inline void *guest_addr_to_host(struct kvm *self, unsigned long offset)
+{
+       return self->ram_start + offset;
+}
+
+static bool kvm__supports_extension(struct kvm *self, unsigned int extension)
 {
        int ret;
 
@@ -54,7 +73,7 @@ static struct kvm *kvm__new(void)
        return self;
 }
 
-static struct kvm *kvm__init(void)
+struct kvm *kvm__init(void)
 {
        struct kvm_userspace_memory_region mem;
        struct kvm *self;
@@ -118,13 +137,7 @@ static struct kvm *kvm__init(void)
        return self;
 }
 
-static void kvm__run(struct kvm *self)
-{
-       if (ioctl(self->vcpu_fd, KVM_RUN, 0) < 0)
-               die_perror("KVM_RUN failed");
-}
-
-static void kvm__enable_singlestep(struct kvm *self)
+void kvm__enable_singlestep(struct kvm *self)
 {
        struct kvm_guest_debug debug = {
                .control        = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP,
@@ -134,68 +147,6 @@ static void kvm__enable_singlestep(struct kvm *self)
                warning("KVM_SET_GUEST_DEBUG failed");
 }
 
-static void kvm__show_registers(struct kvm *self)
-{
-       unsigned long rax, rbx, rcx;
-       unsigned long rdx, rsi, rdi;
-       unsigned long rbp,  r8,  r9;
-       unsigned long r10, r11, r12;
-       unsigned long r13, r14, r15;
-       unsigned long rip, rsp;
-       unsigned long rflags;
-       struct kvm_regs regs;
-
-       if (ioctl(self->vcpu_fd, KVM_GET_REGS, &regs) < 0)
-               die("KVM_GET_REGS failed");
-
-       rflags = regs.rflags;
-
-       rip = regs.rip; rsp = regs.rsp;
-       rax = regs.rax; rbx = regs.rbx; rcx = regs.rcx;
-       rdx = regs.rdx; rsi = regs.rsi; rdi = regs.rdi;
-       rbp = regs.rbp; r8  = regs.r8;  r9  = regs.r9;
-       r10 = regs.r10; r11 = regs.r11; r12 = regs.r12;
-       r13 = regs.r13; r14 = regs.r14; r15 = regs.r15;
-
-       printf("Registers:\n");
-       printf(" rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
-       printf(" rax: %016lx   ebx: %016lx   ecx: %016lx\n", rax, rbx, rcx);
-       printf(" rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
-       printf(" rbp: %016lx   r8:  %016lx   r9:  %016lx\n", rbp, r8,  r9);
-       printf(" r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
-       printf(" r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
-}
-
-static inline void *guest_addr_to_host(struct kvm *self, unsigned long offset)
-{
-       return self->ram_start + offset;
-}
-
-static void kvm__show_code(struct kvm *self)
-{
-       unsigned int code_bytes = 64;
-       unsigned int code_prologue = code_bytes * 43 / 64;
-       unsigned int code_len = code_bytes;
-       unsigned char c;
-       uint8_t *ip;
-       int i;
-
-       ip = guest_addr_to_host(self, self->regs.rip - code_prologue);
-
-       printf("Code: ");
-
-       for (i = 0; i < code_len; i++, ip++) {
-               c = *ip;
-
-               if (ip == guest_addr_to_host(self, self->regs.rip))
-                       printf("<%02x> ", c);
-               else
-                       printf("%02x ", c);
-       }
-
-       printf("\n");
-}
-
 /* bzImages are loaded at 1 MB by default.  */
 #define KERNEL_START_ADDR      (1024ULL * 1024ULL)
 
@@ -222,7 +173,7 @@ static uint32_t load_bzimage(struct kvm *kvm, int fd)
        return boot.hdr.code32_start;
 }
 
-static uint32_t kvm__load_kernel(struct kvm *kvm, const char *kernel_filename)
+uint32_t kvm__load_kernel(struct kvm *kvm, const char *kernel_filename)
 {
        uint32_t ret;
        int fd;
@@ -238,36 +189,7 @@ static uint32_t kvm__load_kernel(struct kvm *kvm, const char *kernel_filename)
        return ret;
 }
 
-#define DEFINE_KVM_EXIT_REASON(reason) [reason] = #reason
-
-static const char *exit_reasons[] = {
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_UNKNOWN),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_EXCEPTION),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_IO),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_HYPERCALL),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_DEBUG),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_HLT),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_MMIO),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_IRQ_WINDOW_OPEN),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_SHUTDOWN),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_FAIL_ENTRY),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTR),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_SET_TPR),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_TPR_ACCESS),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_SIEIC),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_RESET),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_DCR),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_NMI),
-       DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTERNAL_ERROR),
-};
-
-static void usage(char *argv[])
-{
-       fprintf(stderr, "  usage: %s <kernel-image>\n", argv[0]);
-       exit(1);
-}
-
-static void kvm__reset_vcpu(struct kvm *self, uint64_t rip)
+void kvm__reset_vcpu(struct kvm *self, uint64_t rip)
 {
        self->regs.rip          = rip;
        self->regs.rflags       = 0x0000000000000002ULL;
@@ -276,6 +198,12 @@ static void kvm__reset_vcpu(struct kvm *self, uint64_t rip)
                die_perror("KVM_SET_REGS failed");
 }
 
+void kvm__run(struct kvm *self)
+{
+       if (ioctl(self->vcpu_fd, KVM_RUN, 0) < 0)
+               die_perror("KVM_RUN failed");
+}
+
 static void kvm__emulate_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
 {
        fprintf(stderr, "%s port=%x, size=%d, count=%" PRIu32 "\n", __func__, port, size, count);
@@ -286,7 +214,7 @@ static void kvm__emulate_io_in(struct kvm *self, uint16_t port, void *data, int
        fprintf(stderr, "%s port=%x, size=%d, count=%" PRIu32 "\n", __func__, port, size, count);
 }
 
-static void kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int direction, int size, uint32_t count)
+void kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int direction, int size, uint32_t count)
 {
        if (direction == KVM_EXIT_IO_IN)
                kvm__emulate_io_in(self, port, data, size, count);
@@ -294,50 +222,59 @@ static void kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int dir
                kvm__emulate_io_out(self, port, data, size, count);
 }
 
-int main(int argc, char *argv[])
+void kvm__show_registers(struct kvm *self)
 {
-       const char *kernel_filename;
-       uint64_t kernel_start;
-       struct kvm *kvm;
-       int ret;
-
-       if (argc < 2)
-               usage(argv);
+       unsigned long rax, rbx, rcx;
+       unsigned long rdx, rsi, rdi;
+       unsigned long rbp,  r8,  r9;
+       unsigned long r10, r11, r12;
+       unsigned long r13, r14, r15;
+       unsigned long rip, rsp;
+       unsigned long rflags;
+       struct kvm_regs regs;
 
-       kernel_filename = argv[1];
+       if (ioctl(self->vcpu_fd, KVM_GET_REGS, &regs) < 0)
+               die("KVM_GET_REGS failed");
 
-       kvm = kvm__init();
+       rflags = regs.rflags;
 
-       kernel_start = kvm__load_kernel(kvm, kernel_filename);
+       rip = regs.rip; rsp = regs.rsp;
+       rax = regs.rax; rbx = regs.rbx; rcx = regs.rcx;
+       rdx = regs.rdx; rsi = regs.rsi; rdi = regs.rdi;
+       rbp = regs.rbp; r8  = regs.r8;  r9  = regs.r9;
+       r10 = regs.r10; r11 = regs.r11; r12 = regs.r12;
+       r13 = regs.r13; r14 = regs.r14; r15 = regs.r15;
 
-       kvm__reset_vcpu(kvm, kernel_start);
+       printf("Registers:\n");
+       printf(" rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
+       printf(" rax: %016lx   ebx: %016lx   ecx: %016lx\n", rax, rbx, rcx);
+       printf(" rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
+       printf(" rbp: %016lx   r8:  %016lx   r9:  %016lx\n", rbp, r8,  r9);
+       printf(" r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
+       printf(" r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
+}
 
-       kvm__enable_singlestep(kvm);
+void kvm__show_code(struct kvm *self)
+{
+       unsigned int code_bytes = 64;
+       unsigned int code_prologue = code_bytes * 43 / 64;
+       unsigned int code_len = code_bytes;
+       unsigned char c;
+       unsigned int i;
+       uint8_t *ip;
 
-       for (;;) {
-               kvm__run(kvm);
+       ip = guest_addr_to_host(self, self->regs.rip - code_prologue);
 
-               switch (kvm->kvm_run->exit_reason) {
-               case KVM_EXIT_IO:
-                       kvm__emulate_io(kvm,
-                                       kvm->kvm_run->io.port,
-                                       (uint8_t *)kvm->kvm_run + kvm->kvm_run->io.data_offset,
-                                       kvm->kvm_run->io.direction,
-                                       kvm->kvm_run->io.size,
-                                       kvm->kvm_run->io.count);
-                       goto exit_kvm;
-                       break;
-               default:
-                       goto exit_kvm;
-               }
-       }
+       printf("Code: ");
 
-exit_kvm:
-       fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n",
-               kvm->kvm_run->exit_reason, exit_reasons[kvm->kvm_run->exit_reason]);
+       for (i = 0; i < code_len; i++, ip++) {
+               c = *ip;
 
-       kvm__show_registers(kvm);
-       kvm__show_code(kvm);
+               if (ip == guest_addr_to_host(self, self->regs.rip))
+                       printf("<%02x> ", c);
+               else
+                       printf("%02x ", c);
+       }
 
-       return 0;
+       printf("\n");
 }
diff --git a/tools/kvm/main.c b/tools/kvm/main.c
new file mode 100644 (file)
index 0000000..ba0aefa
--- /dev/null
@@ -0,0 +1,59 @@
+#include "kvm/kvm.h"
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static void usage(char *argv[])
+{
+       fprintf(stderr, "  usage: %s <kernel-image>\n", argv[0]);
+       exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+       const char *kernel_filename;
+       uint64_t kernel_start;
+       struct kvm *kvm;
+
+       if (argc < 2)
+               usage(argv);
+
+       kernel_filename = argv[1];
+
+       kvm = kvm__init();
+
+       kernel_start = kvm__load_kernel(kvm, kernel_filename);
+
+       kvm__reset_vcpu(kvm, kernel_start);
+
+       kvm__enable_singlestep(kvm);
+
+       for (;;) {
+               kvm__run(kvm);
+
+               switch (kvm->kvm_run->exit_reason) {
+               case KVM_EXIT_IO:
+                       kvm__emulate_io(kvm,
+                                       kvm->kvm_run->io.port,
+                                       (uint8_t *)kvm->kvm_run + kvm->kvm_run->io.data_offset,
+                                       kvm->kvm_run->io.direction,
+                                       kvm->kvm_run->io.size,
+                                       kvm->kvm_run->io.count);
+                       goto exit_kvm;
+                       break;
+               default:
+                       goto exit_kvm;
+               }
+       }
+
+exit_kvm:
+       fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n",
+               kvm->kvm_run->exit_reason, kvm_exit_reasons[kvm->kvm_run->exit_reason]);
+
+       kvm__show_registers(kvm);
+       kvm__show_code(kvm);
+
+       return 0;
+}