diff mbox

kvm tools: Introduce KVM VCPU data structure

Message ID 1302343631-30060-1-git-send-email-penberg@kernel.org (mailing list archive)
State New, archived
Headers show

Commit Message

Pekka Enberg April 9, 2011, 10:07 a.m. UTC
In preparation for threaded execution model, this patch introduces a KVM VCPU
data structure 'struct kvm_cpu'.

Cc: Asias He <asias.hejun@gmail.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
---
 tools/kvm/Makefile              |    1 +
 tools/kvm/cpuid.c               |    6 +-
 tools/kvm/include/kvm/kvm-cpu.h |   33 ++++
 tools/kvm/include/kvm/kvm.h     |   16 --
 tools/kvm/ioport.c              |    2 +
 tools/kvm/kvm-cpu.c             |  370 +++++++++++++++++++++++++++++++++++++++
 tools/kvm/kvm-run.c             |   62 ++++---
 tools/kvm/kvm.c                 |  338 -----------------------------------
 8 files changed, 445 insertions(+), 383 deletions(-)
 create mode 100644 tools/kvm/include/kvm/kvm-cpu.h
 create mode 100644 tools/kvm/kvm-cpu.c

Comments

Ingo Molnar April 9, 2011, 11:59 a.m. UTC | #1
* Pekka Enberg <penberg@kernel.org> wrote:

> In preparation for threaded execution model, this patch introduces a KVM VCPU
> data structure 'struct kvm_cpu'.
> 
> Cc: Asias He <asias.hejun@gmail.com>
> Cc: Cyrill Gorcunov <gorcunov@gmail.com>
> Cc: Ingo Molnar <mingo@elte.hu>
> Signed-off-by: Pekka Enberg <penberg@kernel.org>
> ---
>  tools/kvm/Makefile              |    1 +
>  tools/kvm/cpuid.c               |    6 +-
>  tools/kvm/include/kvm/kvm-cpu.h |   33 ++++
>  tools/kvm/include/kvm/kvm.h     |   16 --
>  tools/kvm/ioport.c              |    2 +
>  tools/kvm/kvm-cpu.c             |  370 +++++++++++++++++++++++++++++++++++++++
>  tools/kvm/kvm-run.c             |   62 ++++---
>  tools/kvm/kvm.c                 |  338 -----------------------------------
>  8 files changed, 445 insertions(+), 383 deletions(-)
>  create mode 100644 tools/kvm/include/kvm/kvm-cpu.h
>  create mode 100644 tools/kvm/kvm-cpu.c

This commit causes a segfault for 'kvm run bzImage':

(gdb) set args run bzImage
(gdb) run
Starting program: /home/mingo/tip/tools/kvm/kvm run bzImage
[Thread debugging using libthread_db enabled]

Program received signal SIGSEGV, Segmentation fault.
0x0000000000405054 in setup_bios (kvm=0x68a010) at bios.c:106
106		memset(p, 0, BDA_END - BDA_START);
Missing separate debuginfos, use: debuginfo-install glibc-2.13-1.x86_64
(gdb) bt
#0  0x0000000000405054 in setup_bios (kvm=0x68a010) at bios.c:106
#1  0x0000000000404ef5 in kvm_cmd_run (argc=<value optimized out>, argv=<value optimized out>, 
    prefix=<value optimized out>) at kvm-run.c:160
#2  0x00000000004038cf in handle_kvm_command (argc=<value optimized out>, argv=<value optimized out>)
    at main.c:16
#3  main (argc=<value optimized out>, argv=<value optimized out>) at main.c:21
(gdb) q
A debugging session is active.

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Cyrill Gorcunov April 9, 2011, 12:25 p.m. UTC | #2
On 04/09/2011 03:59 PM, Ingo Molnar wrote:
> 
> * Pekka Enberg <penberg@kernel.org> wrote:
> 
>> In preparation for threaded execution model, this patch introduces a KVM VCPU
>> data structure 'struct kvm_cpu'.
>>
>> Cc: Asias He <asias.hejun@gmail.com>
>> Cc: Cyrill Gorcunov <gorcunov@gmail.com>
>> Cc: Ingo Molnar <mingo@elte.hu>
>> Signed-off-by: Pekka Enberg <penberg@kernel.org>
>> ---
...
> 
> This commit causes a segfault for 'kvm run bzImage':
> 
> (gdb) set args run bzImage
> (gdb) run
> Starting program: /home/mingo/tip/tools/kvm/kvm run bzImage
> [Thread debugging using libthread_db enabled]
> 
> Program received signal SIGSEGV, Segmentation fault.
> 0x0000000000405054 in setup_bios (kvm=0x68a010) at bios.c:106
> 106		memset(p, 0, BDA_END - BDA_START);

Ugh, Pekka, was the memory properly mmaped? Setup bios called multiple
times in every thread?
Ingo Molnar April 9, 2011, 12:26 p.m. UTC | #3
* Ingo Molnar <mingo@elte.hu> wrote:

> This commit causes a segfault for 'kvm run bzImage':

Weird - i tried to debug it, then the bug went away. I'm using the same sha1 
now as before, but the crash does not trigger. Very weird.

But this definitely started triggering today and never triggered before, so 
it's something recent.

Tanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ingo Molnar April 9, 2011, 12:27 p.m. UTC | #4
* Cyrill Gorcunov <gorcunov@gmail.com> wrote:

> On 04/09/2011 03:59 PM, Ingo Molnar wrote:
> > 
> > * Pekka Enberg <penberg@kernel.org> wrote:
> > 
> >> In preparation for threaded execution model, this patch introduces a KVM VCPU
> >> data structure 'struct kvm_cpu'.
> >>
> >> Cc: Asias He <asias.hejun@gmail.com>
> >> Cc: Cyrill Gorcunov <gorcunov@gmail.com>
> >> Cc: Ingo Molnar <mingo@elte.hu>
> >> Signed-off-by: Pekka Enberg <penberg@kernel.org>
> >> ---
> ...
> > 
> > This commit causes a segfault for 'kvm run bzImage':
> > 
> > (gdb) set args run bzImage
> > (gdb) run
> > Starting program: /home/mingo/tip/tools/kvm/kvm run bzImage
> > [Thread debugging using libthread_db enabled]
> > 
> > Program received signal SIGSEGV, Segmentation fault.
> > 0x0000000000405054 in setup_bios (kvm=0x68a010) at bios.c:106
> > 106		memset(p, 0, BDA_END - BDA_START);
> 
> Ugh, Pekka, was the memory properly mmaped? Setup bios called multiple
> times in every thread?

Why should mmap() be called in every thread?

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pekka Enberg April 9, 2011, 12:30 p.m. UTC | #5
On Sat, 9 Apr 2011, Ingo Molnar wrote:
> Weird - i tried to debug it, then the bug went away. I'm using the same sha1
> now as before, but the crash does not trigger. Very weird.
>
> But this definitely started triggering today and never triggered before, so
> it's something recent.

Let me guess, you did 'make clean'? I think our header dep checking might 
be busted in the Makefile...

 			Pekka
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Cyrill Gorcunov April 9, 2011, 12:33 p.m. UTC | #6
On 04/09/2011 04:27 PM, Ingo Molnar wrote:
...
>>
>> Ugh, Pekka, was the memory properly mmaped? Setup bios called multiple
>> times in every thread?
> 
> Why should mmap() be called in every thread?
> 
> Thanks,
> 
> 	Ingo

I thought it being called for some reason.
I'm not updated to this threaded model yet.
Pekka Enberg April 9, 2011, 12:34 p.m. UTC | #7
On Sat, 9 Apr 2011, Cyrill Gorcunov wrote:
> I thought it being called for some reason.
> I'm not updated to this threaded model yet.

None of the fancy stuff is merged. It's likely just because of struct 
layout changes combined with broken header dep checking.

 			Pekka
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Cyrill Gorcunov April 9, 2011, 12:35 p.m. UTC | #8
On 04/09/2011 04:34 PM, Pekka Enberg wrote:
> On Sat, 9 Apr 2011, Cyrill Gorcunov wrote:
>> I thought it being called for some reason.
>> I'm not updated to this threaded model yet.
> 
> None of the fancy stuff is merged. It's likely just because of struct layout changes combined with broken header dep checking.
> 
>             Pekka

ah, ok, this might explain. While the sources are small, maybe we should call make clean all the time?
Ingo Molnar April 9, 2011, 12:36 p.m. UTC | #9
* Pekka Enberg <penberg@kernel.org> wrote:

> On Sat, 9 Apr 2011, Ingo Molnar wrote:
> >Weird - i tried to debug it, then the bug went away. I'm using the same sha1
> >now as before, but the crash does not trigger. Very weird.
> >
> >But this definitely started triggering today and never triggered before, so
> >it's something recent.
> 
> Let me guess, you did 'make clean'? I think our header dep checking
> might be busted in the Makefile...

That indeed could be it.

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pekka Enberg April 9, 2011, 12:38 p.m. UTC | #10
On Sat, 9 Apr 2011, Cyrill Gorcunov wrote:
> ah, ok, this might explain. While the sources are small, maybe we should call make clean all the time?

We should just fix the Makefile. :-)
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index 4bcfd74..141cdec 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -21,6 +21,7 @@  OBJS	+= disk-image.o
 OBJS	+= interrupt.o
 OBJS	+= ioport.o
 OBJS	+= kvm.o
+OBJS	+= kvm-cpu.o
 OBJS	+= main.o
 OBJS	+= mmio.o
 OBJS	+= pci.o
diff --git a/tools/kvm/cpuid.c b/tools/kvm/cpuid.c
index f7cc930..0b26eb1 100644
--- a/tools/kvm/cpuid.c
+++ b/tools/kvm/cpuid.c
@@ -1,3 +1,5 @@ 
+#include "kvm/kvm-cpu.h"
+
 #include "kvm/kvm.h"
 #include "kvm/util.h"
 
@@ -30,14 +32,14 @@  static void filter_cpuid(struct kvm_cpuid2 *kvm_cpuid)
 	}
 }
 
-void kvm__setup_cpuid(struct kvm *self)
+void kvm_cpu__setup_cpuid(struct kvm_cpu *self)
 {
 	struct kvm_cpuid2 *kvm_cpuid;
 
 	kvm_cpuid = calloc(1, sizeof(*kvm_cpuid) + MAX_KVM_CPUID_ENTRIES * sizeof(*kvm_cpuid->entries));
 
 	kvm_cpuid->nent = MAX_KVM_CPUID_ENTRIES;
-	if (ioctl(self->sys_fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) < 0)
+	if (ioctl(self->kvm->sys_fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) < 0)
 		die_perror("KVM_GET_SUPPORTED_CPUID failed");
 
 	filter_cpuid(kvm_cpuid);
diff --git a/tools/kvm/include/kvm/kvm-cpu.h b/tools/kvm/include/kvm/kvm-cpu.h
new file mode 100644
index 0000000..d36dadf
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm-cpu.h
@@ -0,0 +1,33 @@ 
+#ifndef KVM__KVM_CPU_H
+#define KVM__KVM_CPU_H
+
+#include <linux/kvm.h>	/* for struct kvm_regs */
+
+#include <stdint.h>
+
+struct kvm;
+
+struct kvm_cpu {
+	struct kvm		*kvm;		/* parent KVM */
+	int			vcpu_fd;	/* For VCPU ioctls() */
+	struct kvm_run		*kvm_run;
+
+	struct kvm_regs		regs;
+	struct kvm_sregs	sregs;
+	struct kvm_fpu		fpu;
+
+	struct kvm_msrs		*msrs;		/* dynamically allocated */
+};
+
+struct kvm_cpu *kvm_cpu__init(struct kvm *kvm);
+void kvm_cpu__delete(struct kvm_cpu *self);
+void kvm_cpu__reset_vcpu(struct kvm_cpu *self);
+void kvm_cpu__setup_cpuid(struct kvm_cpu *self);
+void kvm_cpu__enable_singlestep(struct kvm_cpu *self);
+void kvm_cpu__run(struct kvm_cpu *self);
+
+void kvm_cpu__show_code(struct kvm_cpu *self);
+void kvm_cpu__show_registers(struct kvm_cpu *self);
+void kvm_cpu__show_page_tables(struct kvm_cpu *self);
+
+#endif /* KVM__KVM_CPU_H */
diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
index a099307..7af98f9 100644
--- a/tools/kvm/include/kvm/kvm.h
+++ b/tools/kvm/include/kvm/kvm.h
@@ -3,8 +3,6 @@ 
 
 #include "kvm/interrupt.h"
 
-#include <linux/kvm.h>	/* for struct kvm_regs */
-
 #include <stdbool.h>
 #include <stdint.h>
 #include <time.h>
@@ -12,9 +10,7 @@ 
 struct kvm {
 	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
 	int			vm_fd;		/* For VM ioctls() */
-	int			vcpu_fd;	/* For VCPU ioctls() */
 	timer_t			timerid;	/* Posix timer for interrupts */
-	struct kvm_run		*kvm_run;
 
 	struct disk_image	*disk_image;
 	uint64_t		ram_size;
@@ -26,25 +22,16 @@  struct kvm {
 	uint16_t		boot_ip;
 	uint16_t		boot_sp;
 
-	struct kvm_regs		regs;
-	struct kvm_sregs	sregs;
-	struct kvm_fpu		fpu;
-	struct kvm_msrs		*msrs;	/* dynamically allocated */
-
 	struct interrupt_table	interrupt_table;
 };
 
 struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size);
 void kvm__delete(struct kvm *self);
-void kvm__setup_cpuid(struct kvm *self);
-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_bios(struct kvm *self);
 void kvm__start_timer(struct kvm *self);
 void kvm__stop_timer(struct kvm *self);
-void kvm__run(struct kvm *self);
 void kvm__irq_line(struct kvm *self, int irq, int level);
 bool kvm__emulate_io(struct kvm *self, uint16_t port, void *data, int direction, int size, uint32_t count);
 bool kvm__emulate_mmio(struct kvm *self, uint64_t phys_addr, uint8_t *data, uint32_t len, uint8_t is_write);
@@ -52,9 +39,6 @@  bool kvm__emulate_mmio(struct kvm *self, uint64_t phys_addr, uint8_t *data, uint
 /*
  * Debugging
  */
-void kvm__show_code(struct kvm *self);
-void kvm__show_registers(struct kvm *self);
-void kvm__show_page_tables(struct kvm *self);
 void kvm__dump_mem(struct kvm *self, unsigned long addr, unsigned long size);
 
 extern const char *kvm_exit_reasons[];
diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c
index 4579e89..6303571 100644
--- a/tools/kvm/ioport.c
+++ b/tools/kvm/ioport.c
@@ -2,6 +2,8 @@ 
 
 #include "kvm/kvm.h"
 
+#include <linux/kvm.h>	/* for KVM_EXIT_* */
+
 #include <stdbool.h>
 #include <assert.h>
 #include <limits.h>
diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
new file mode 100644
index 0000000..374adb2
--- /dev/null
+++ b/tools/kvm/kvm-cpu.c
@@ -0,0 +1,370 @@ 
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+
+static inline bool is_in_protected_mode(struct kvm_cpu *self)
+{
+	return self->sregs.cr0 & 0x01;
+}
+
+static inline uint64_t ip_to_flat(struct kvm_cpu *self, uint64_t ip)
+{
+	uint64_t cs;
+
+	/*
+	 * NOTE! We should take code segment base address into account here.
+	 * Luckily it's usually zero because Linux uses flat memory model.
+	 */
+	if (is_in_protected_mode(self))
+		return ip;
+
+	cs = self->sregs.cs.selector;
+
+	return ip + (cs << 4);
+}
+
+static inline uint32_t selector_to_base(uint16_t selector)
+{
+	/*
+	 * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
+	 */
+	return (uint32_t)selector * 16;
+}
+
+static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
+{
+	struct kvm_cpu *self;
+
+	self		= calloc(1, sizeof *self);
+	if (!self)
+		return NULL;
+
+	self->kvm	= kvm;
+
+	return self;
+}
+
+void kvm_cpu__delete(struct kvm_cpu *self)
+{
+	if (self->msrs)
+		free(self->msrs);
+
+	free(self);
+}
+
+struct kvm_cpu *kvm_cpu__init(struct kvm *kvm)
+{
+	struct kvm_cpu *self;
+	int mmap_size;
+
+	self		= kvm_cpu__new(kvm);
+	if (!self)
+		return NULL;
+
+	self->vcpu_fd = ioctl(self->kvm->vm_fd, KVM_CREATE_VCPU, 0);
+	if (self->vcpu_fd < 0)
+		die_perror("KVM_CREATE_VCPU ioctl");
+
+	mmap_size = ioctl(self->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
+	if (mmap_size < 0)
+		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
+
+	self->kvm_run = mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, self->vcpu_fd, 0);
+	if (self->kvm_run == MAP_FAILED)
+		die("unable to mmap vcpu fd");
+
+	return self;
+}
+
+void kvm_cpu__enable_singlestep(struct kvm_cpu *self)
+{
+	struct kvm_guest_debug debug = {
+		.control	= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP,
+	};
+
+	if (ioctl(self->vcpu_fd, KVM_SET_GUEST_DEBUG, &debug) < 0)
+		warning("KVM_SET_GUEST_DEBUG failed");
+}
+
+static struct kvm_msrs *kvm_msrs__new(size_t nmsrs)
+{
+	struct kvm_msrs *self = calloc(1, sizeof(*self) + (sizeof(struct kvm_msr_entry) * nmsrs));
+
+	if (!self)
+		die("out of memory");
+
+	return self;
+}
+
+#define MSR_IA32_TIME_STAMP_COUNTER	0x10
+
+#define MSR_IA32_SYSENTER_CS		0x174
+#define MSR_IA32_SYSENTER_ESP		0x175
+#define MSR_IA32_SYSENTER_EIP		0x176
+
+#define MSR_IA32_STAR			0xc0000081
+#define MSR_IA32_LSTAR			0xc0000082
+#define MSR_IA32_CSTAR			0xc0000083
+#define MSR_IA32_FMASK			0xc0000084
+#define MSR_IA32_KERNEL_GS_BASE		0xc0000102
+
+#define KVM_MSR_ENTRY(_index, _data)	\
+	(struct kvm_msr_entry) { .index = _index, .data = _data }
+
+static void kvm_cpu__setup_msrs(struct kvm_cpu *self)
+{
+	unsigned long ndx = 0;
+
+	self->msrs = kvm_msrs__new(100);
+
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_CS,	0x0);
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_ESP,	0x0);
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_EIP,	0x0);
+#ifdef CONFIG_X86_64
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_STAR,		0x0);
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_CSTAR,		0x0);
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_KERNEL_GS_BASE,	0x0);
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_FMASK,		0x0);
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_LSTAR,		0x0);
+#endif
+	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_TIME_STAMP_COUNTER,	0x0);
+
+	self->msrs->nmsrs	= ndx;
+
+	if (ioctl(self->vcpu_fd, KVM_SET_MSRS, self->msrs) < 0)
+		die_perror("KVM_SET_MSRS failed");
+}
+
+static void kvm_cpu__setup_fpu(struct kvm_cpu *self)
+{
+	self->fpu = (struct kvm_fpu) {
+		.fcw		= 0x37f,
+		.mxcsr		= 0x1f80,
+	};
+
+	if (ioctl(self->vcpu_fd, KVM_SET_FPU, &self->fpu) < 0)
+		die_perror("KVM_SET_FPU failed");
+}
+
+static void kvm_cpu__setup_regs(struct kvm_cpu *self)
+{
+	self->regs = (struct kvm_regs) {
+		/* We start the guest in 16-bit real mode  */
+		.rflags		= 0x0000000000000002ULL,
+
+		.rip		= self->kvm->boot_ip,
+		.rsp		= self->kvm->boot_sp,
+		.rbp		= self->kvm->boot_sp,
+	};
+
+	if (self->regs.rip > USHRT_MAX)
+		die("ip 0x%" PRIx64 " is too high for real mode", (uint64_t) self->regs.rip);
+
+	if (ioctl(self->vcpu_fd, KVM_SET_REGS, &self->regs) < 0)
+		die_perror("KVM_SET_REGS failed");
+}
+
+static void kvm_cpu__setup_sregs(struct kvm_cpu *self)
+{
+
+	if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &self->sregs) < 0)
+		die_perror("KVM_GET_SREGS failed");
+
+	self->sregs.cs.selector	= self->kvm->boot_selector;
+	self->sregs.cs.base	= selector_to_base(self->kvm->boot_selector);
+	self->sregs.ss.selector	= self->kvm->boot_selector;
+	self->sregs.ss.base	= selector_to_base(self->kvm->boot_selector);
+	self->sregs.ds.selector	= self->kvm->boot_selector;
+	self->sregs.ds.base	= selector_to_base(self->kvm->boot_selector);
+	self->sregs.es.selector	= self->kvm->boot_selector;
+	self->sregs.es.base	= selector_to_base(self->kvm->boot_selector);
+	self->sregs.fs.selector	= self->kvm->boot_selector;
+	self->sregs.fs.base	= selector_to_base(self->kvm->boot_selector);
+	self->sregs.gs.selector	= self->kvm->boot_selector;
+	self->sregs.gs.base	= selector_to_base(self->kvm->boot_selector);
+
+	if (ioctl(self->vcpu_fd, KVM_SET_SREGS, &self->sregs) < 0)
+		die_perror("KVM_SET_SREGS failed");
+}
+
+/**
+ * kvm_cpu__reset_vcpu - reset virtual CPU to a known state
+ */
+void kvm_cpu__reset_vcpu(struct kvm_cpu *self)
+{
+	kvm_cpu__setup_sregs(self);
+	kvm_cpu__setup_regs(self);
+	kvm_cpu__setup_fpu(self);
+	kvm_cpu__setup_msrs(self);
+}
+
+static void print_dtable(const char *name, struct kvm_dtable *dtable)
+{
+	printf(" %s                 %016" PRIx64 "  %08" PRIx16 "\n",
+		name, (uint64_t) dtable->base, (uint16_t) dtable->limit);
+}
+
+static void print_segment(const char *name, struct kvm_segment *seg)
+{
+	printf(" %s       %04" PRIx16 "      %016" PRIx64 "  %08" PRIx32 "  %02" PRIx8 "    %x %x   %x  %x %x %x %x\n",
+		name, (uint16_t) seg->selector, (uint64_t) seg->base, (uint32_t) seg->limit,
+		(uint8_t) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
+}
+
+void kvm_cpu__show_registers(struct kvm_cpu *self)
+{
+	unsigned long cr0, cr2, cr3;
+	unsigned long cr4, cr8;
+	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;
+	struct kvm_sregs sregs;
+	unsigned long rflags;
+	struct kvm_regs regs;
+	int i;
+
+	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   rbx: %016lx   rcx: %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);
+
+	if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
+		die("KVM_GET_REGS failed");
+
+	cr0 = sregs.cr0; cr2 = sregs.cr2; cr3 = sregs.cr3;
+	cr4 = sregs.cr4; cr8 = sregs.cr8;
+
+	printf(" cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
+	printf(" cr4: %016lx   cr8: %016lx\n", cr4, cr8);
+	printf("Segment registers:\n");
+	printf(" register  selector  base              limit     type  p dpl db s l g avl\n");
+	print_segment("cs ", &sregs.cs);
+	print_segment("ss ", &sregs.ss);
+	print_segment("ds ", &sregs.ds);
+	print_segment("es ", &sregs.es);
+	print_segment("fs ", &sregs.fs);
+	print_segment("gs ", &sregs.gs);
+	print_segment("tr ", &sregs.tr);
+	print_segment("ldt", &sregs.ldt);
+	print_dtable("gdt", &sregs.gdt);
+	print_dtable("idt", &sregs.idt);
+	printf(" [ efer: %016" PRIx64 "  apic base: %016" PRIx64 "  nmi: %s ]\n",
+		(uint64_t) sregs.efer, (uint64_t) sregs.apic_base,
+		(self->kvm->nmi_disabled ? "disabled" : "enabled"));
+	printf("Interrupt bitmap:\n");
+	printf(" ");
+	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
+		printf("%016" PRIx64 " ", (uint64_t) sregs.interrupt_bitmap[i]);
+	printf("\n");
+}
+
+void kvm_cpu__show_code(struct kvm_cpu *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;
+
+	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_flat_to_host(self->kvm, ip_to_flat(self, self->regs.rip) - code_prologue);
+
+	printf("Code: ");
+
+	for (i = 0; i < code_len; i++, ip++) {
+		if (!host_ptr_in_ram(self->kvm, ip))
+			break;
+
+		c = *ip;
+
+		if (ip == guest_flat_to_host(self->kvm, ip_to_flat(self, self->regs.rip)))
+			printf("<%02x> ", c);
+		else
+			printf("%02x ", c);
+	}
+
+	printf("\n");
+
+	printf("Stack:\n");
+	kvm__dump_mem(self->kvm, self->regs.rsp, 32);
+}
+
+void kvm_cpu__show_page_tables(struct kvm_cpu *self)
+{
+	uint64_t *pte1;
+	uint64_t *pte2;
+	uint64_t *pte3;
+	uint64_t *pte4;
+
+	if (!is_in_protected_mode(self))
+		return;
+
+	if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &self->sregs) < 0)
+		die("KVM_GET_SREGS failed");
+
+	pte4	= guest_flat_to_host(self->kvm, self->sregs.cr3);
+	if (!host_ptr_in_ram(self->kvm, pte4))
+		return;
+
+	pte3	= guest_flat_to_host(self->kvm, (*pte4 & ~0xfff));
+	if (!host_ptr_in_ram(self->kvm, pte3))
+		return;
+
+	pte2	= guest_flat_to_host(self->kvm, (*pte3 & ~0xfff));
+	if (!host_ptr_in_ram(self->kvm, pte2))
+		return;
+
+	pte1	= guest_flat_to_host(self->kvm, (*pte2 & ~0xfff));
+	if (!host_ptr_in_ram(self->kvm, pte1))
+		return;
+
+	printf("Page Tables:\n");
+	if (*pte2 & (1 << 7))
+		printf(" pte4: %016" PRIx64 "   pte3: %016" PRIx64
+			"   pte2: %016" PRIx64 "\n",
+			*pte4, *pte3, *pte2);
+	else
+		printf(" pte4: %016" PRIx64 "   pte3: %016" PRIx64 "   pte2: %016"
+			PRIx64 "   pte1: %016" PRIx64 "\n",
+			*pte4, *pte3, *pte2, *pte1);
+}
+
+void kvm_cpu__run(struct kvm_cpu *self)
+{
+	int err;
+
+	err = ioctl(self->vcpu_fd, KVM_RUN, 0);
+	if (err && (errno != EINTR && errno != EAGAIN))
+		die_perror("KVM_RUN failed");
+}
diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
index 9b0786a..9392818 100644
--- a/tools/kvm/kvm-run.c
+++ b/tools/kvm/kvm-run.c
@@ -10,6 +10,7 @@ 
 /* user defined header files */
 #include <linux/types.h>
 #include <kvm/kvm.h>
+#include <kvm/kvm-cpu.h>
 #include <kvm/8250-serial.h>
 #include <kvm/virtio-blk.h>
 #include <kvm/virtio-console.h>
@@ -29,6 +30,7 @@ 
 #define MIN_RAM_SIZE_BYTE	(MIN_RAM_SIZE_MB << MB_SHIFT)
 
 static struct kvm *kvm;
+static struct kvm_cpu *cpu;
 
 static void handle_sigint(int sig)
 {
@@ -37,10 +39,11 @@  static void handle_sigint(int sig)
 
 static void handle_sigquit(int sig)
 {
-	kvm__show_registers(kvm);
-	kvm__show_code(kvm);
-	kvm__show_page_tables(kvm);
+	kvm_cpu__show_registers(cpu);
+	kvm_cpu__show_code(cpu);
+	kvm_cpu__show_page_tables(cpu);
 
+	kvm_cpu__delete(cpu);
 	kvm__delete(kvm);
 
 	exit(1);
@@ -130,13 +133,17 @@  int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	kvm = kvm__init(kvm_dev, ram_size);
 
+	cpu = kvm_cpu__init(kvm);
+	if (!cpu)
+		die("unable to initialize KVM VCPU");
+
 	if (image_filename) {
 		kvm->disk_image	= disk_image__open(image_filename);
 		if (!kvm->disk_image)
 			die("unable to load disk image %s", image_filename);
 	}
 
-	kvm__setup_cpuid(kvm);
+	kvm_cpu__setup_cpuid(cpu);
 
 	strcpy(real_cmdline, "notsc nolapic noacpi pci=conf1 console=ttyS0 ");
 	if (!kernel_cmdline || !strstr(kernel_cmdline, "root=")) {
@@ -153,12 +160,12 @@  int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 				real_cmdline))
 		die("unable to load kernel %s", kernel_filename);
 
-	kvm__reset_vcpu(kvm);
+	kvm_cpu__reset_vcpu(cpu);
 
 	kvm__setup_bios(kvm);
 
 	if (single_step)
-		kvm__enable_singlestep(kvm);
+		kvm_cpu__enable_singlestep(cpu);
 
 	serial8250__init(kvm);
 
@@ -171,23 +178,23 @@  int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 	kvm__start_timer(kvm);
 
 	for (;;) {
-		kvm__run(kvm);
+		kvm_cpu__run(cpu);
 
-		switch (kvm->kvm_run->exit_reason) {
+		switch (cpu->kvm_run->exit_reason) {
 		case KVM_EXIT_DEBUG:
-			kvm__show_registers(kvm);
-			kvm__show_code(kvm);
+			kvm_cpu__show_registers(cpu);
+			kvm_cpu__show_code(cpu);
 			break;
 		case KVM_EXIT_IO: {
 			bool ret;
 
 			ret = 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);
+					cpu->kvm_run->io.port,
+					(uint8_t *)cpu->kvm_run +
+					cpu->kvm_run->io.data_offset,
+					cpu->kvm_run->io.direction,
+					cpu->kvm_run->io.size,
+					cpu->kvm_run->io.count);
 
 			if (!ret)
 				goto panic_kvm;
@@ -197,10 +204,10 @@  int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 			bool ret;
 
 			ret = kvm__emulate_mmio(kvm,
-					kvm->kvm_run->mmio.phys_addr,
-					kvm->kvm_run->mmio.data,
-					kvm->kvm_run->mmio.len,
-					kvm->kvm_run->mmio.is_write);
+					cpu->kvm_run->mmio.phys_addr,
+					cpu->kvm_run->mmio.data,
+					cpu->kvm_run->mmio.len,
+					cpu->kvm_run->mmio.is_write);
 
 			if (!ret)
 				goto panic_kvm;
@@ -227,15 +234,16 @@  exit_kvm:
 
 panic_kvm:
 	fprintf(stderr, "KVM exit reason: %" PRIu32 " (\"%s\")\n",
-		kvm->kvm_run->exit_reason,
-		kvm_exit_reasons[kvm->kvm_run->exit_reason]);
-	if (kvm->kvm_run->exit_reason == KVM_EXIT_UNKNOWN)
+		cpu->kvm_run->exit_reason,
+		kvm_exit_reasons[cpu->kvm_run->exit_reason]);
+	if (cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN)
 		fprintf(stderr, "KVM exit code: 0x%" PRIu64 "\n",
-			kvm->kvm_run->hw.hardware_exit_reason);
+			cpu->kvm_run->hw.hardware_exit_reason);
 	disk_image__close(kvm->disk_image);
-	kvm__show_registers(kvm);
-	kvm__show_code(kvm);
-	kvm__show_page_tables(kvm);
+	kvm_cpu__show_registers(cpu);
+	kvm_cpu__show_code(cpu);
+	kvm_cpu__show_page_tables(cpu);
+	kvm_cpu__delete(cpu);
 	kvm__delete(kvm);
 
 	return 1;
diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
index 2cd206d..af1f65f 100644
--- a/tools/kvm/kvm.c
+++ b/tools/kvm/kvm.c
@@ -107,9 +107,6 @@  void kvm__delete(struct kvm *self)
 {
 	kvm__stop_timer(self);
 
-	if (self->msrs)
-		free(self->msrs);
-
 	free(self->ram_start);
 	free(self);
 }
@@ -162,7 +159,6 @@  struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size)
 	struct kvm_pit_config pit_config = { .flags = 0, };
 	struct kvm *self;
 	long page_size;
-	int mmap_size;
 	int ret;
 
 	if (!kvm__cpu_supports_vm())
@@ -222,31 +218,9 @@  struct kvm *kvm__init(const char *kvm_dev, unsigned long ram_size)
 	if (ret < 0)
 		die_perror("KVM_CREATE_IRQCHIP ioctl");
 
-	self->vcpu_fd = ioctl(self->vm_fd, KVM_CREATE_VCPU, 0);
-	if (self->vcpu_fd < 0)
-		die_perror("KVM_CREATE_VCPU ioctl");
-
-	mmap_size = ioctl(self->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
-	if (mmap_size < 0)
-		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
-
-	self->kvm_run = mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, self->vcpu_fd, 0);
-	if (self->kvm_run == MAP_FAILED)
-		die("unable to mmap vcpu fd");
-
 	return self;
 }
 
-void kvm__enable_singlestep(struct kvm *self)
-{
-	struct kvm_guest_debug debug = {
-		.control	= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP,
-	};
-
-	if (ioctl(self->vcpu_fd, KVM_SET_GUEST_DEBUG, &debug) < 0)
-		warning("KVM_SET_GUEST_DEBUG failed");
-}
-
 #define BOOT_LOADER_SELECTOR	0x1000
 #define BOOT_LOADER_IP		0x0000
 #define BOOT_LOADER_SP		0x8000
@@ -417,154 +391,6 @@  found_kernel:
 	return ret;
 }
 
-static inline uint64_t ip_flat_to_real(struct kvm *self, uint64_t ip)
-{
-	uint64_t cs = self->sregs.cs.selector;
-
-	return ip - (cs << 4);
-}
-
-static inline bool is_in_protected_mode(struct kvm *self)
-{
-	return self->sregs.cr0 & 0x01;
-}
-
-static inline uint64_t ip_to_flat(struct kvm *self, uint64_t ip)
-{
-	uint64_t cs;
-
-	/*
-	 * NOTE! We should take code segment base address into account here.
-	 * Luckily it's usually zero because Linux uses flat memory model.
-	 */
-	if (is_in_protected_mode(self))
-		return ip;
-
-	cs = self->sregs.cs.selector;
-
-	return ip + (cs << 4);
-}
-
-static inline uint32_t selector_to_base(uint16_t selector)
-{
-	/*
-	 * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
-	 */
-	return (uint32_t)selector * 16;
-}
-
-static struct kvm_msrs *kvm_msrs__new(size_t nmsrs)
-{
-	struct kvm_msrs *self = calloc(1, sizeof(*self) + (sizeof(struct kvm_msr_entry) * nmsrs));
-
-	if (!self)
-		die("out of memory");
-
-	return self;
-}
-
-#define MSR_IA32_TIME_STAMP_COUNTER	0x10
-
-#define MSR_IA32_SYSENTER_CS		0x174
-#define MSR_IA32_SYSENTER_ESP		0x175
-#define MSR_IA32_SYSENTER_EIP		0x176
-
-#define MSR_IA32_STAR			0xc0000081
-#define MSR_IA32_LSTAR			0xc0000082
-#define MSR_IA32_CSTAR			0xc0000083
-#define MSR_IA32_FMASK			0xc0000084
-#define MSR_IA32_KERNEL_GS_BASE		0xc0000102
-
-#define KVM_MSR_ENTRY(_index, _data)	\
-	(struct kvm_msr_entry) { .index = _index, .data = _data }
-
-static void kvm__setup_msrs(struct kvm *self)
-{
-	unsigned long ndx = 0;
-
-	self->msrs = kvm_msrs__new(100);
-
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_CS,	0x0);
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_ESP,	0x0);
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_EIP,	0x0);
-#ifdef CONFIG_X86_64
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_STAR,		0x0);
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_CSTAR,		0x0);
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_KERNEL_GS_BASE,	0x0);
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_FMASK,		0x0);
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_LSTAR,		0x0);
-#endif
-	self->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_TIME_STAMP_COUNTER,	0x0);
-
-	self->msrs->nmsrs	= ndx;
-
-	if (ioctl(self->vcpu_fd, KVM_SET_MSRS, self->msrs) < 0)
-		die_perror("KVM_SET_MSRS failed");
-}
-
-static void kvm__setup_fpu(struct kvm *self)
-{
-	self->fpu = (struct kvm_fpu) {
-		.fcw		= 0x37f,
-		.mxcsr		= 0x1f80,
-	};
-
-	if (ioctl(self->vcpu_fd, KVM_SET_FPU, &self->fpu) < 0)
-		die_perror("KVM_SET_FPU failed");
-}
-
-static void kvm__setup_regs(struct kvm *self)
-{
-	self->regs = (struct kvm_regs) {
-		/* We start the guest in 16-bit real mode  */
-		.rflags		= 0x0000000000000002ULL,
-
-		.rip		= self->boot_ip,
-		.rsp		= self->boot_sp,
-		.rbp		= self->boot_sp,
-	};
-
-	if (self->regs.rip > USHRT_MAX)
-		die("ip 0x%" PRIx64 " is too high for real mode", (uint64_t) self->regs.rip);
-
-	if (ioctl(self->vcpu_fd, KVM_SET_REGS, &self->regs) < 0)
-		die_perror("KVM_SET_REGS failed");
-}
-
-static void kvm__setup_sregs(struct kvm *self)
-{
-
-	if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &self->sregs) < 0)
-		die_perror("KVM_GET_SREGS failed");
-
-	self->sregs.cs.selector	= self->boot_selector;
-	self->sregs.cs.base	= selector_to_base(self->boot_selector);
-	self->sregs.ss.selector	= self->boot_selector;
-	self->sregs.ss.base	= selector_to_base(self->boot_selector);
-	self->sregs.ds.selector	= self->boot_selector;
-	self->sregs.ds.base	= selector_to_base(self->boot_selector);
-	self->sregs.es.selector	= self->boot_selector;
-	self->sregs.es.base	= selector_to_base(self->boot_selector);
-	self->sregs.fs.selector	= self->boot_selector;
-	self->sregs.fs.base	= selector_to_base(self->boot_selector);
-	self->sregs.gs.selector	= self->boot_selector;
-	self->sregs.gs.base	= selector_to_base(self->boot_selector);
-
-	if (ioctl(self->vcpu_fd, KVM_SET_SREGS, &self->sregs) < 0)
-		die_perror("KVM_SET_SREGS failed");
-}
-
-/**
- * kvm__reset_vcpu - reset virtual CPU to a known state
- */
-void kvm__reset_vcpu(struct kvm *self)
-{
-	kvm__setup_sregs(self);
-	kvm__setup_regs(self);
-	kvm__setup_fpu(self);
-	kvm__setup_msrs(self);
-}
-
 /**
  * kvm__setup_bios - inject BIOS into guest system memory
  * @self - guest system descriptor
@@ -629,15 +455,6 @@  void kvm__stop_timer(struct kvm *self)
 	self->timerid = 0;
 }
 
-void kvm__run(struct kvm *self)
-{
-	int err;
-
-	err = ioctl(self->vcpu_fd, KVM_RUN, 0);
-	if (err && (errno != EINTR && errno != EAGAIN))
-		die_perror("KVM_RUN failed");
-}
-
 void kvm__irq_line(struct kvm *self, int irq, int level)
 {
 	struct kvm_irq_level irq_level;
@@ -653,161 +470,6 @@  void kvm__irq_line(struct kvm *self, int irq, int level)
 		die_perror("KVM_IRQ_LINE failed");
 }
 
-static void print_dtable(const char *name, struct kvm_dtable *dtable)
-{
-	printf(" %s                 %016" PRIx64 "  %08" PRIx16 "\n",
-		name, (uint64_t) dtable->base, (uint16_t) dtable->limit);
-}
-
-static void print_segment(const char *name, struct kvm_segment *seg)
-{
-	printf(" %s       %04" PRIx16 "      %016" PRIx64 "  %08" PRIx32 "  %02" PRIx8 "    %x %x   %x  %x %x %x %x\n",
-		name, (uint16_t) seg->selector, (uint64_t) seg->base, (uint32_t) seg->limit,
-		(uint8_t) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
-}
-
-void kvm__show_registers(struct kvm *self)
-{
-	unsigned long cr0, cr2, cr3;
-	unsigned long cr4, cr8;
-	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;
-	struct kvm_sregs sregs;
-	unsigned long rflags;
-	struct kvm_regs regs;
-	int i;
-
-	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   rbx: %016lx   rcx: %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);
-
-	if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
-		die("KVM_GET_REGS failed");
-
-	cr0 = sregs.cr0; cr2 = sregs.cr2; cr3 = sregs.cr3;
-	cr4 = sregs.cr4; cr8 = sregs.cr8;
-
-	printf(" cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
-	printf(" cr4: %016lx   cr8: %016lx\n", cr4, cr8);
-	printf("Segment registers:\n");
-	printf(" register  selector  base              limit     type  p dpl db s l g avl\n");
-	print_segment("cs ", &sregs.cs);
-	print_segment("ss ", &sregs.ss);
-	print_segment("ds ", &sregs.ds);
-	print_segment("es ", &sregs.es);
-	print_segment("fs ", &sregs.fs);
-	print_segment("gs ", &sregs.gs);
-	print_segment("tr ", &sregs.tr);
-	print_segment("ldt", &sregs.ldt);
-	print_dtable("gdt", &sregs.gdt);
-	print_dtable("idt", &sregs.idt);
-	printf(" [ efer: %016" PRIx64 "  apic base: %016" PRIx64 "  nmi: %s ]\n",
-		(uint64_t) sregs.efer, (uint64_t) sregs.apic_base,
-		(self->nmi_disabled ? "disabled" : "enabled"));
-	printf("Interrupt bitmap:\n");
-	printf(" ");
-	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
-		printf("%016" PRIx64 " ", (uint64_t) sregs.interrupt_bitmap[i]);
-	printf("\n");
-}
-
-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;
-
-	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_flat_to_host(self, ip_to_flat(self, self->regs.rip) - code_prologue);
-
-	printf("Code: ");
-
-	for (i = 0; i < code_len; i++, ip++) {
-		if (!host_ptr_in_ram(self, ip))
-			break;
-
-		c = *ip;
-
-		if (ip == guest_flat_to_host(self, ip_to_flat(self, self->regs.rip)))
-			printf("<%02x> ", c);
-		else
-			printf("%02x ", c);
-	}
-
-	printf("\n");
-
-	printf("Stack:\n");
-	kvm__dump_mem(self, self->regs.rsp, 32);
-}
-
-void kvm__show_page_tables(struct kvm *self)
-{
-	uint64_t *pte1;
-	uint64_t *pte2;
-	uint64_t *pte3;
-	uint64_t *pte4;
-
-	if (!is_in_protected_mode(self))
-		return;
-
-	if (ioctl(self->vcpu_fd, KVM_GET_SREGS, &self->sregs) < 0)
-		die("KVM_GET_SREGS failed");
-
-	pte4	= guest_flat_to_host(self, self->sregs.cr3);
-	if (!host_ptr_in_ram(self, pte4))
-		return;
-
-	pte3	= guest_flat_to_host(self, (*pte4 & ~0xfff));
-	if (!host_ptr_in_ram(self, pte3))
-		return;
-
-	pte2	= guest_flat_to_host(self, (*pte3 & ~0xfff));
-	if (!host_ptr_in_ram(self, pte2))
-		return;
-
-	pte1	= guest_flat_to_host(self, (*pte2 & ~0xfff));
-	if (!host_ptr_in_ram(self, pte1))
-		return;
-
-	printf("Page Tables:\n");
-	if (*pte2 & (1 << 7))
-		printf(" pte4: %016" PRIx64 "   pte3: %016" PRIx64
-			"   pte2: %016" PRIx64 "\n",
-			*pte4, *pte3, *pte2);
-	else
-		printf(" pte4: %016" PRIx64 "   pte3: %016" PRIx64 "   pte2: %016"
-			PRIx64 "   pte1: %016" PRIx64 "\n",
-			*pte4, *pte3, *pte2, *pte1);
-}
-
 void kvm__dump_mem(struct kvm *self, unsigned long addr, unsigned long size)
 {
 	unsigned char *p;