All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <levinsasha928@gmail.com>
To: Matt Evans <matt@ozlabs.org>
Cc: kvm@vger.kernel.org, kvm-ppc@vger.kernel.org
Subject: Re: [PATCH 01/28] kvm tools: Split x86 arch-specific bits into x86/
Date: Tue, 06 Dec 2011 08:07:46 +0000	[thread overview]
Message-ID: <1323158866.3882.2.camel@lappy> (raw)
In-Reply-To: <4EDD8DED.3070908@ozlabs.org>

The code doesn't build after this patch due to missing header issues
which you fixed in patches #10 & #11. Could you please move those two to
the beginning of the series for the sake of bisectablilty?

On Tue, 2011-12-06 at 14:37 +1100, Matt Evans wrote:
> Create a new arch-specific subdirectory to contain architecture-specific code
> and includes.
> 
> The Makefile now adds various arch-specific objects based on detected
> architecture.  That aside, this patch should only contain code moves.  These
> include:
> 
> - x86-specific kvm_cpu setup, kernel loading, memory setup etc. now in
>   x86/kvm{-cpu}.c
> - BIOS now lives in x86/bios/
> - ioport setup
> - KVM extensions are asserted in arch-specific kvm.c now, so each architecture
>   can manage its own dependencies.
> - Various architecture-specific #defines are moved into $(ARCH)/include/kvm{-cpu}.h
>   such as struct kvm_cpu, KVM_NR_CPUS, KVM_32BIT_GAP_SIZE.
> 
> Signed-off-by: Matt Evans <matt@ozlabs.org>
> ---
>  tools/kvm/Makefile                              |   96 ++++---
>  tools/kvm/builtin-run.c                         |    6 +-
>  tools/kvm/include/kvm/ioport.h                  |    2 +-
>  tools/kvm/include/kvm/kvm-cpu.h                 |   27 +--
>  tools/kvm/include/kvm/kvm.h                     |   58 +---
>  tools/kvm/ioport.c                              |   54 ----
>  tools/kvm/kvm-cpu.c                             |  372 ----------------------
>  tools/kvm/kvm.c                                 |  323 +-------------------
>  tools/kvm/{ => x86}/bios.c                      |    0
>  tools/kvm/{ => x86}/bios/.gitignore             |    0
>  tools/kvm/{ => x86}/bios/bios-rom.S             |    2 +-
>  tools/kvm/{ => x86}/bios/e820.c                 |    0
>  tools/kvm/{ => x86}/bios/entry.S                |    0
>  tools/kvm/{ => x86}/bios/gen-offsets.sh         |    0
>  tools/kvm/{ => x86}/bios/int10.c                |    0
>  tools/kvm/{ => x86}/bios/int15.c                |    0
>  tools/kvm/{ => x86}/bios/local.S                |    0
>  tools/kvm/{ => x86}/bios/macro.S                |    0
>  tools/kvm/{ => x86}/bios/memcpy.c               |    0
>  tools/kvm/{ => x86}/bios/rom.ld.S               |    0
>  tools/kvm/{ => x86}/cpuid.c                     |    0
>  tools/kvm/{ => x86}/include/kvm/assembly.h      |    0
>  tools/kvm/{ => x86}/include/kvm/barrier.h       |    0
>  tools/kvm/{ => x86}/include/kvm/bios-export.h   |    0
>  tools/kvm/{ => x86}/include/kvm/bios.h          |    0
>  tools/kvm/{ => x86}/include/kvm/boot-protocol.h |    0
>  tools/kvm/{ => x86}/include/kvm/cpufeature.h    |    0
>  tools/kvm/{ => x86}/include/kvm/interrupt.h     |    0
>  tools/kvm/x86/include/kvm/kvm-arch.h            |   59 ++++
>  tools/kvm/x86/include/kvm/kvm-cpu-arch.h        |   33 ++
>  tools/kvm/{ => x86}/include/kvm/mptable.h       |    0
>  tools/kvm/{ => x86}/interrupt.c                 |    0
>  tools/kvm/x86/ioport.c                          |   59 ++++
>  tools/kvm/{ => x86}/irq.c                       |    0
>  tools/kvm/x86/kvm-cpu.c                         |  383 +++++++++++++++++++++++
>  tools/kvm/x86/kvm.c                             |  330 +++++++++++++++++++
>  tools/kvm/{ => x86}/mptable.c                   |    0
>  37 files changed, 951 insertions(+), 853 deletions(-)
>  rename tools/kvm/{ => x86}/bios.c (100%)
>  rename tools/kvm/{ => x86}/bios/.gitignore (100%)
>  rename tools/kvm/{ => x86}/bios/bios-rom.S (80%)
>  rename tools/kvm/{ => x86}/bios/e820.c (100%)
>  rename tools/kvm/{ => x86}/bios/entry.S (100%)
>  rename tools/kvm/{ => x86}/bios/gen-offsets.sh (100%)
>  rename tools/kvm/{ => x86}/bios/int10.c (100%)
>  rename tools/kvm/{ => x86}/bios/int15.c (100%)
>  rename tools/kvm/{ => x86}/bios/local.S (100%)
>  rename tools/kvm/{ => x86}/bios/macro.S (100%)
>  rename tools/kvm/{ => x86}/bios/memcpy.c (100%)
>  rename tools/kvm/{ => x86}/bios/rom.ld.S (100%)
>  rename tools/kvm/{ => x86}/cpuid.c (100%)
>  rename tools/kvm/{ => x86}/include/kvm/assembly.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/barrier.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/bios-export.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/bios.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/boot-protocol.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/cpufeature.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/interrupt.h (100%)
>  create mode 100644 tools/kvm/x86/include/kvm/kvm-arch.h
>  create mode 100644 tools/kvm/x86/include/kvm/kvm-cpu-arch.h
>  rename tools/kvm/{ => x86}/include/kvm/mptable.h (100%)
>  rename tools/kvm/{ => x86}/interrupt.c (100%)
>  create mode 100644 tools/kvm/x86/ioport.c
>  rename tools/kvm/{ => x86}/irq.c (100%)
>  create mode 100644 tools/kvm/x86/kvm-cpu.c
>  create mode 100644 tools/kvm/x86/kvm.c
>  rename tools/kvm/{ => x86}/mptable.c (100%)
> 
> diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
> index bb5f6b0..243886e 100644
> --- a/tools/kvm/Makefile
> +++ b/tools/kvm/Makefile
> @@ -33,13 +33,11 @@ OBJS	+= builtin-run.o
>  OBJS	+= builtin-setup.o
>  OBJS	+= builtin-stop.o
>  OBJS	+= builtin-version.o
> -OBJS	+= cpuid.o
>  OBJS	+= disk/core.o
>  OBJS	+= framebuffer.o
>  OBJS	+= guest_compat.o
>  OBJS	+= hw/rtc.o
>  OBJS	+= hw/serial.o
> -OBJS	+= interrupt.o
>  OBJS	+= ioport.o
>  OBJS	+= kvm-cpu.o
>  OBJS	+= kvm.o
> @@ -61,7 +59,6 @@ OBJS	+= disk/blk.o
>  OBJS	+= disk/qcow.o
>  OBJS	+= disk/raw.o
>  OBJS	+= ioeventfd.o
> -OBJS	+= irq.o
>  OBJS	+= net/uip/core.o
>  OBJS	+= net/uip/arp.o
>  OBJS	+= net/uip/icmp.o
> @@ -72,7 +69,6 @@ OBJS	+= net/uip/buf.o
>  OBJS	+= net/uip/csum.o
>  OBJS	+= net/uip/dhcp.o
>  OBJS	+= kvm-cmd.o
> -OBJS	+= mptable.o
>  OBJS	+= rbtree.o
>  OBJS	+= threadpool.o
>  OBJS	+= util/parse-options.o
> @@ -123,12 +119,6 @@ ifeq ($(has_AIO),y)
>  	LIBS	+= -laio
>  endif
>  
> -DEPS	:= $(patsubst %.o,%.d,$(OBJS))
> -
> -# Exclude BIOS object files from header dependencies.
> -OBJS	+= bios.o
> -OBJS	+= bios/bios-rom.o
> -
>  LIBS	+= -lrt
>  LIBS	+= -lpthread
>  LIBS	+= -lutil
> @@ -150,12 +140,43 @@ ifeq ($(uname_M),x86_64)
>  	DEFINES      += -DCONFIG_X86_64
>  endif
>  
> +
> +### Arch-specific stuff
> +
> +#x86
> +ifeq ($(ARCH),x86)
> +	DEFINES += -DCONFIG_X86
> +	OBJS	+= x86/cpuid.o
> +	OBJS	+= x86/interrupt.o
> +	OBJS	+= x86/ioport.o
> +	OBJS	+= x86/irq.o
> +	OBJS	+= x86/kvm.o
> +	OBJS	+= x86/kvm-cpu.o
> +	OBJS	+= x86/mptable.o
> +# Exclude BIOS object files from header dependencies.
> +	OTHEROBJS	+= x86/bios.o
> +	OTHEROBJS	+= x86/bios/bios-rom.o
> +	ARCH_INCLUDE := x86/include
> +endif
> +
> +###
> +
> +ifeq (,$(ARCH_INCLUDE))
> +	UNSUPP_ERR = @echo "This architecture is not supported in kvmtool." && exit 1
> +else
> +	UNSUPP_ERR > +endif
> +
> +DEPS	:= $(patsubst %.o,%.d,$(OBJS))
> +OBJS	+= $(OTHEROBJS)
> +
>  DEFINES	+= -D_FILE_OFFSET_BITSd
>  DEFINES	+= -D_GNU_SOURCE
>  DEFINES	+= -DKVMTOOLS_VERSION='"$(KVMTOOLS_VERSION)"'
> +DEFINES	+= -DBUILD_ARCH='"$(ARCH)"'
>  
>  KVM_INCLUDE := include
> -CFLAGS	+= $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -Os -g
> +CFLAGS	+= $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I$(ARCH_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -Os -g
>  
>  ifneq ($(WERROR),0)
>  	WARNINGS += -Werror
> @@ -179,7 +200,10 @@ WARNINGS += -Wwrite-strings
>  
>  CFLAGS	+= $(WARNINGS)
>  
> -all: $(PROGRAM) $(GUEST_INIT)
> +all: arch_support_check $(PROGRAM) $(GUEST_INIT)
> +
> +arch_support_check:
> +	$(UNSUPP_ERR)
>  
>  KVMTOOLS-VERSION-FILE:
>  	@$(SHELL_PATH) util/KVMTOOLS-VERSION-GEN $(OUTPUT)
> @@ -227,33 +251,33 @@ BIOS_CFLAGS += -mregparm=3
>  BIOS_CFLAGS += -fno-stack-protector
>  BIOS_CFLAGS += -I../../arch/$(ARCH)
>  
> -bios.o: bios/bios.bin bios/bios-rom.h
> -
> -bios/bios.bin.elf: bios/entry.S bios/e820.c bios/int10.c bios/int15.c bios/rom.ld.S
> -	$(E) "  CC       bios/memcpy.o"
> -	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/memcpy.c -o bios/memcpy.o
> -	$(E) "  CC       bios/e820.o"
> -	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/e820.c -o bios/e820.o
> -	$(E) "  CC       bios/int10.o"
> -	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/int10.c -o bios/int10.o
> -	$(E) "  CC       bios/int15.o"
> -	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/int15.c -o bios/int15.o
> -	$(E) "  CC       bios/entry.o"
> -	$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/entry.S -o bios/entry.o
> +x86/bios.o: x86/bios/bios.bin x86/bios/bios-rom.h
> +
> +x86/bios/bios.bin.elf: x86/bios/entry.S x86/bios/e820.c x86/bios/int10.c x86/bios/int15.c x86/bios/rom.ld.S
> +	$(E) "  CC       x86/bios/memcpy.o"
> +	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/memcpy.c -o x86/bios/memcpy.o
> +	$(E) "  CC       x86/bios/e820.o"
> +	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/e820.c -o x86/bios/e820.o
> +	$(E) "  CC       x86/bios/int10.o"
> +	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/int10.c -o x86/bios/int10.o
> +	$(E) "  CC       x86/bios/int15.o"
> +	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/int15.c -o x86/bios/int15.o
> +	$(E) "  CC       x86/bios/entry.o"
> +	$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/entry.S -o x86/bios/entry.o
>  	$(E) "  LD      " $@
> -	$(Q) ld -T bios/rom.ld.S -o bios/bios.bin.elf bios/memcpy.o bios/entry.o bios/e820.o bios/int10.o bios/int15.o
> +	$(Q) ld -T x86/bios/rom.ld.S -o x86/bios/bios.bin.elf x86/bios/memcpy.o x86/bios/entry.o x86/bios/e820.o x86/bios/int10.o x86/bios/int15.o
>  
> -bios/bios.bin: bios/bios.bin.elf
> +x86/bios/bios.bin: x86/bios/bios.bin.elf
>  	$(E) "  OBJCOPY " $@
> -	$(Q) objcopy -O binary -j .text bios/bios.bin.elf bios/bios.bin
> +	$(Q) objcopy -O binary -j .text x86/bios/bios.bin.elf x86/bios/bios.bin
>  
> -bios/bios-rom.o: bios/bios-rom.S bios/bios.bin bios/bios-rom.h
> +x86/bios/bios-rom.o: x86/bios/bios-rom.S x86/bios/bios.bin x86/bios/bios-rom.h
>  	$(E) "  CC      " $@
> -	$(Q) $(CC) -c $(CFLAGS) bios/bios-rom.S -o bios/bios-rom.o
> +	$(Q) $(CC) -c $(CFLAGS) x86/bios/bios-rom.S -o x86/bios/bios-rom.o
>  
> -bios/bios-rom.h: bios/bios.bin.elf
> +x86/bios/bios-rom.h: x86/bios/bios.bin.elf
>  	$(E) "  NM      " $@
> -	$(Q) cd bios && sh gen-offsets.sh > bios-rom.h && cd ..
> +	$(Q) cd x86/bios && sh gen-offsets.sh > bios-rom.h && cd ..
>  
>  check: $(PROGRAM)
>  	$(MAKE) -C tests
> @@ -263,10 +287,10 @@ check: $(PROGRAM)
>  
>  clean:
>  	$(E) "  CLEAN"
> -	$(Q) rm -f bios/*.bin
> -	$(Q) rm -f bios/*.elf
> -	$(Q) rm -f bios/*.o
> -	$(Q) rm -f bios/bios-rom.h
> +	$(Q) rm -f x86/bios/*.bin
> +	$(Q) rm -f x86/bios/*.elf
> +	$(Q) rm -f x86/bios/*.o
> +	$(Q) rm -f x86/bios/bios-rom.h
>  	$(Q) rm -f tests/boot/boot_test.iso
>  	$(Q) rm -rf tests/boot/rootfs/
>  	$(Q) rm -f $(DEPS) $(OBJS) $(PROGRAM) $(GUEST_INIT)
> diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
> index 33de4f6..9148d83 100644
> --- a/tools/kvm/builtin-run.c
> +++ b/tools/kvm/builtin-run.c
> @@ -568,7 +568,7 @@ static const char *host_kernels[] = {
>  
>  static const char *default_kernels[] = {
>  	"./bzImage",
> -	"../../arch/x86/boot/bzImage",
> +	"../../arch/" BUILD_ARCH "/boot/bzImage",
>  	NULL
>  };
>  
> @@ -886,7 +886,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
>  
>  	kvm->vmlinux		= vmlinux_filename;
>  
> -	ioport__setup_legacy();
> +	ioport__setup_arch();
>  
>  	rtc__init();
>  
> @@ -931,7 +931,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
>  
>  	kvm__start_timer(kvm);
>  
> -	kvm__setup_bios(kvm);
> +	kvm__arch_setup_firmware(kvm);
>  
>  	for (i = 0; i < nrcpus; i++) {
>  		kvm_cpus[i] = kvm_cpu__init(kvm, i);
> diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
> index 5b857dd..61a70ec 100644
> --- a/tools/kvm/include/kvm/ioport.h
> +++ b/tools/kvm/include/kvm/ioport.h
> @@ -28,7 +28,7 @@ struct ioport_operations {
>  	bool (*io_out)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size);
>  };
>  
> -void ioport__setup_legacy(void);
> +void ioport__setup_arch(void);
>  
>  u16 ioport__register(u16 port, struct ioport_operations *ops, int count, void *param);
>  
> diff --git a/tools/kvm/include/kvm/kvm-cpu.h b/tools/kvm/include/kvm/kvm-cpu.h
> index 01540ac..719e286 100644
> --- a/tools/kvm/include/kvm/kvm-cpu.h
> +++ b/tools/kvm/include/kvm/kvm-cpu.h
> @@ -1,32 +1,7 @@
>  #ifndef KVM__KVM_CPU_H
>  #define KVM__KVM_CPU_H
>  
> -#include <linux/kvm.h>	/* for struct kvm_regs */
> -
> -#include <pthread.h>
> -
> -struct kvm;
> -
> -struct kvm_cpu {
> -	pthread_t		thread;		/* VCPU thread */
> -
> -	unsigned long		cpu_id;
> -
> -	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 */
> -
> -	u8			is_running;
> -	u8			paused;
> -
> -	struct kvm_coalesced_mmio_ring	*ring;
> -};
> +#include "kvm/kvm-cpu-arch.h"
>  
>  struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id);
>  void kvm_cpu__delete(struct kvm_cpu *vcpu);
> diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
> index 2b3024a..ca1acc0 100644
> --- a/tools/kvm/include/kvm/kvm.h
> +++ b/tools/kvm/include/kvm/kvm.h
> @@ -1,22 +1,13 @@
>  #ifndef KVM__KVM_H
>  #define KVM__KVM_H
>  
> -#include "kvm/interrupt.h"
> -#include "kvm/segment.h"
> +#include "kvm/kvm-arch.h"
>  
>  #include <stdbool.h>
>  #include <linux/types.h>
>  #include <time.h>
>  #include <signal.h>
>  
> -#define KVM_NR_CPUS		(255)
> -
> -/*
> - * The hole includes VESA framebuffer and PCI memory.
> - */
> -#define KVM_32BIT_GAP_SIZE	(768 << 20)
> -#define KVM_32BIT_GAP_START	((1ULL << 32) - KVM_32BIT_GAP_SIZE)
> -
>  #define SIGKVMEXIT		(SIGRTMIN + 0)
>  #define SIGKVMPAUSE		(SIGRTMIN + 1)
>  #define SIGKVMSTOP		(SIGRTMIN + 4)
> @@ -25,33 +16,15 @@
>  #define KVM_PID_FILE_PATH	"/.kvm-tools/"
>  #define HOME_DIR		getenv("HOME")
>  
> -struct kvm {
> -	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
> -	int			vm_fd;		/* For VM ioctls() */
> -	timer_t			timerid;	/* Posix timer for interrupts */
> -
> -	int			nrcpus;		/* Number of cpus to run */
> -
> -	u32			mem_slots;	/* for KVM_SET_USER_MEMORY_REGION */
> -
> -	u64			ram_size;
> -	void			*ram_start;
> -
> -	bool			nmi_disabled;
> -
> -	bool			single_step;
> +#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
>  
> -	u16			boot_selector;
> -	u16			boot_ip;
> -	u16			boot_sp;
> +#define DEFINE_KVM_EXT(ext)		\
> +	.name = #ext,			\
> +	.code = ext
>  
> -	struct interrupt_table	interrupt_table;
> -
> -	const char		*vmlinux;
> -	struct disk_image       **disks;
> -	int                     nr_disks;
> -
> -	const char		*name;
> +struct kvm_ext {
> +	const char *name;
> +	int code;
>  };
>  
>  void kvm__set_dir(const char *fmt, ...);
> @@ -64,7 +37,6 @@ void kvm__init_ram(struct kvm *kvm);
>  void kvm__delete(struct kvm *kvm);
>  bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
>  			const char *initrd_filename, const char *kernel_cmdline, u16 vidmode);
> -void kvm__setup_bios(struct kvm *kvm);
>  void kvm__start_timer(struct kvm *kvm);
>  void kvm__stop_timer(struct kvm *kvm);
>  void kvm__irq_line(struct kvm *kvm, int irq, int level);
> @@ -81,6 +53,13 @@ int kvm__get_sock_by_instance(const char *name);
>  int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
>  void kvm__remove_socket(const char *name);
>  
> +void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name);
> +void kvm__arch_setup_firmware(struct kvm *kvm);
> +bool kvm__arch_cpu_supports_vm(void);
> +
> +int load_flat_binary(struct kvm *kvm, int fd);
> +bool load_bzimage(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline, u16 vidmode);
> +
>  /*
>   * Debugging
>   */
> @@ -98,11 +77,4 @@ static inline void *guest_flat_to_host(struct kvm *kvm, unsigned long offset)
>  	return kvm->ram_start + offset;
>  }
>  
> -static inline void *guest_real_to_host(struct kvm *kvm, u16 selector, u16 offset)
> -{
> -	unsigned long flat = segment_to_flat(selector, offset);
> -
> -	return guest_flat_to_host(kvm, flat);
> -}
> -
>  #endif /* KVM__KVM_H */
> diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c
> index 7cbc44e..965cfc2 100644
> --- a/tools/kvm/ioport.c
> +++ b/tools/kvm/ioport.c
> @@ -52,34 +52,6 @@ static int ioport_insert(struct rb_root *root, struct ioport *data)
>  	return rb_int_insert(root, &data->node);
>  }
>  
> -static bool debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> -{
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static struct ioport_operations debug_ops = {
> -	.io_out		= debug_io_out,
> -};
> -
> -static bool dummy_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> -{
> -	return true;
> -}
> -
> -static bool dummy_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> -{
> -	return true;
> -}
> -
> -static struct ioport_operations dummy_read_write_ioport_ops = {
> -	.io_in		= dummy_io_in,
> -	.io_out		= dummy_io_out,
> -};
> -
> -static struct ioport_operations dummy_write_only_ioport_ops = {
> -	.io_out		= dummy_io_out,
> -};
> -
>  u16 ioport__register(u16 port, struct ioport_operations *ops, int count, void *param)
>  {
>  	struct ioport *entry;
> @@ -164,29 +136,3 @@ error:
>  
>  	return !ioport_debug;
>  }
> -
> -void ioport__setup_legacy(void)
> -{
> -	/* 0x0020 - 0x003F - 8259A PIC 1 */
> -	ioport__register(0x0020, &dummy_read_write_ioport_ops, 2, NULL);
> -
> -	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
> -	ioport__register(0x0040, &dummy_read_write_ioport_ops, 4, NULL);
> -
> -	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
> -	ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
> -
> -	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
> -	   internal debugging purposes.  */
> -	ioport__register(IOPORT_DBG, &debug_ops, 1, NULL);
> -
> -	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
> -	ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
> -
> -	/* 0x00F0 - 0x00FF - Math co-processor */
> -	ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
> -
> -	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
> -	ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
> -	ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
> -}
> diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
> index 0ad6f3b..5aba3bb 100644
> --- a/tools/kvm/kvm-cpu.c
> +++ b/tools/kvm/kvm-cpu.c
> @@ -4,8 +4,6 @@
>  #include "kvm/util.h"
>  #include "kvm/kvm.h"
>  
> -#include <asm/msr-index.h>
> -
>  #include <sys/ioctl.h>
>  #include <sys/mman.h>
>  #include <signal.h>
> @@ -14,106 +12,9 @@
>  #include <errno.h>
>  #include <stdio.h>
>  
> -#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
> -
>  extern struct kvm_cpu *kvm_cpus[KVM_NR_CPUS];
>  extern __thread struct kvm_cpu *current_kvm_cpu;
>  
> -static int debug_fd;
> -
> -void kvm_cpu__set_debug_fd(int fd)
> -{
> -	debug_fd = fd;
> -}
> -
> -int kvm_cpu__get_debug_fd(void)
> -{
> -	return debug_fd;
> -}
> -
> -static inline bool is_in_protected_mode(struct kvm_cpu *vcpu)
> -{
> -	return vcpu->sregs.cr0 & 0x01;
> -}
> -
> -static inline u64 ip_to_flat(struct kvm_cpu *vcpu, u64 ip)
> -{
> -	u64 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(vcpu))
> -		return ip;
> -
> -	cs = vcpu->sregs.cs.selector;
> -
> -	return ip + (cs << 4);
> -}
> -
> -static inline u32 selector_to_base(u16 selector)
> -{
> -	/*
> -	 * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
> -	 */
> -	return (u32)selector * 16;
> -}
> -
> -static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
> -{
> -	struct kvm_cpu *vcpu;
> -
> -	vcpu		= calloc(1, sizeof *vcpu);
> -	if (!vcpu)
> -		return NULL;
> -
> -	vcpu->kvm	= kvm;
> -
> -	return vcpu;
> -}
> -
> -void kvm_cpu__delete(struct kvm_cpu *vcpu)
> -{
> -	if (vcpu->msrs)
> -		free(vcpu->msrs);
> -
> -	free(vcpu);
> -}
> -
> -struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id)
> -{
> -	struct kvm_cpu *vcpu;
> -	int mmap_size;
> -	int coalesced_offset;
> -
> -	vcpu		= kvm_cpu__new(kvm);
> -	if (!vcpu)
> -		return NULL;
> -
> -	vcpu->cpu_id	= cpu_id;
> -
> -	vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
> -	if (vcpu->vcpu_fd < 0)
> -		die_perror("KVM_CREATE_VCPU ioctl");
> -
> -	mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
> -	if (mmap_size < 0)
> -		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
> -
> -	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
> -	if (vcpu->kvm_run = MAP_FAILED)
> -		die("unable to mmap vcpu fd");
> -
> -	coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
> -	if (coalesced_offset)
> -		vcpu->ring = (void *)vcpu->kvm_run + (coalesced_offset * PAGE_SIZE);
> -
> -	vcpu->is_running = true;
> -
> -	return vcpu;
> -}
> -
>  void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
>  {
>  	struct kvm_guest_debug debug = {
> @@ -124,278 +25,6 @@ void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
>  		pr_warning("KVM_SET_GUEST_DEBUG failed");
>  }
>  
> -static struct kvm_msrs *kvm_msrs__new(size_t nmsrs)
> -{
> -	struct kvm_msrs *vcpu = calloc(1, sizeof(*vcpu) + (sizeof(struct kvm_msr_entry) * nmsrs));
> -
> -	if (!vcpu)
> -		die("out of memory");
> -
> -	return vcpu;
> -}
> -
> -#define KVM_MSR_ENTRY(_index, _data)	\
> -	(struct kvm_msr_entry) { .index = _index, .data = _data }
> -
> -static void kvm_cpu__setup_msrs(struct kvm_cpu *vcpu)
> -{
> -	unsigned long ndx = 0;
> -
> -	vcpu->msrs = kvm_msrs__new(100);
> -
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_CS,	0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_ESP,	0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_EIP,	0x0);
> -#ifdef CONFIG_X86_64
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_STAR,			0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_CSTAR,			0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_KERNEL_GS_BASE,		0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_SYSCALL_MASK,		0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_LSTAR,			0x0);
> -#endif
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_TSC,		0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_MISC_ENABLE,
> -						MSR_IA32_MISC_ENABLE_FAST_STRING);
> -
> -	vcpu->msrs->nmsrs	= ndx;
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_SET_MSRS, vcpu->msrs) < 0)
> -		die_perror("KVM_SET_MSRS failed");
> -}
> -
> -static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
> -{
> -	vcpu->fpu = (struct kvm_fpu) {
> -		.fcw		= 0x37f,
> -		.mxcsr		= 0x1f80,
> -	};
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_SET_FPU, &vcpu->fpu) < 0)
> -		die_perror("KVM_SET_FPU failed");
> -}
> -
> -static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
> -{
> -	vcpu->regs = (struct kvm_regs) {
> -		/* We start the guest in 16-bit real mode  */
> -		.rflags		= 0x0000000000000002ULL,
> -
> -		.rip		= vcpu->kvm->boot_ip,
> -		.rsp		= vcpu->kvm->boot_sp,
> -		.rbp		= vcpu->kvm->boot_sp,
> -	};
> -
> -	if (vcpu->regs.rip > USHRT_MAX)
> -		die("ip 0x%llx is too high for real mode", (u64) vcpu->regs.rip);
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
> -		die_perror("KVM_SET_REGS failed");
> -}
> -
> -static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
> -{
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> -		die_perror("KVM_GET_SREGS failed");
> -
> -	vcpu->sregs.cs.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.cs.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.ss.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.ss.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.ds.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.ds.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.es.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.es.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.fs.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.fs.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.gs.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.gs.base	= selector_to_base(vcpu->kvm->boot_selector);
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_SET_SREGS, &vcpu->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 *vcpu)
> -{
> -	kvm_cpu__setup_sregs(vcpu);
> -	kvm_cpu__setup_regs(vcpu);
> -	kvm_cpu__setup_fpu(vcpu);
> -	kvm_cpu__setup_msrs(vcpu);
> -}
> -
> -static void print_dtable(const char *name, struct kvm_dtable *dtable)
> -{
> -	dprintf(debug_fd, " %s                 %016llx  %08hx\n",
> -		name, (u64) dtable->base, (u16) dtable->limit);
> -}
> -
> -static void print_segment(const char *name, struct kvm_segment *seg)
> -{
> -	dprintf(debug_fd, " %s       %04hx      %016llx  %08x  %02hhx    %x %x   %x  %x %x %x %x\n",
> -		name, (u16) seg->selector, (u64) seg->base, (u32) seg->limit,
> -		(u8) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
> -}
> -
> -void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
> -{
> -	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(vcpu->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;
> -
> -	dprintf(debug_fd, "\n Registers:\n");
> -	dprintf(debug_fd,   " ----------\n");
> -	dprintf(debug_fd, " rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
> -	dprintf(debug_fd, " rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
> -	dprintf(debug_fd, " rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
> -	dprintf(debug_fd, " rbp: %016lx    r8: %016lx    r9: %016lx\n", rbp, r8,  r9);
> -	dprintf(debug_fd, " r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
> -	dprintf(debug_fd, " r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
> -
> -	if (ioctl(vcpu->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;
> -
> -	dprintf(debug_fd, " cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
> -	dprintf(debug_fd, " cr4: %016lx   cr8: %016lx\n", cr4, cr8);
> -	dprintf(debug_fd, "\n Segment registers:\n");
> -	dprintf(debug_fd,   " ------------------\n");
> -	dprintf(debug_fd, " 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);
> -
> -	dprintf(debug_fd, "\n APIC:\n");
> -	dprintf(debug_fd,   " -----\n");
> -	dprintf(debug_fd, " efer: %016llx  apic base: %016llx  nmi: %s\n",
> -		(u64) sregs.efer, (u64) sregs.apic_base,
> -		(vcpu->kvm->nmi_disabled ? "disabled" : "enabled"));
> -
> -	dprintf(debug_fd, "\n Interrupt bitmap:\n");
> -	dprintf(debug_fd,   " -----------------\n");
> -	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
> -		dprintf(debug_fd, " %016llx", (u64) sregs.interrupt_bitmap[i]);
> -	dprintf(debug_fd, "\n");
> -}
> -
> -#define MAX_SYM_LEN		128
> -
> -void kvm_cpu__show_code(struct kvm_cpu *vcpu)
> -{
> -	unsigned int code_bytes = 64;
> -	unsigned int code_prologue = code_bytes * 43 / 64;
> -	unsigned int code_len = code_bytes;
> -	char sym[MAX_SYM_LEN];
> -	unsigned char c;
> -	unsigned int i;
> -	u8 *ip;
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
> -		die("KVM_GET_REGS failed");
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> -		die("KVM_GET_SREGS failed");
> -
> -	ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip) - code_prologue);
> -
> -	dprintf(debug_fd, "\n Code:\n");
> -	dprintf(debug_fd,   " -----\n");
> -
> -	symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
> -
> -	dprintf(debug_fd, " rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
> -
> -	for (i = 0; i < code_len; i++, ip++) {
> -		if (!host_ptr_in_ram(vcpu->kvm, ip))
> -			break;
> -
> -		c = *ip;
> -
> -		if (ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip)))
> -			dprintf(debug_fd, " <%02x>", c);
> -		else
> -			dprintf(debug_fd, " %02x", c);
> -	}
> -
> -	dprintf(debug_fd, "\n");
> -
> -	dprintf(debug_fd, "\n Stack:\n");
> -	dprintf(debug_fd,   " ------\n");
> -	kvm__dump_mem(vcpu->kvm, vcpu->regs.rsp, 32);
> -}
> -
> -void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
> -{
> -	u64 *pte1;
> -	u64 *pte2;
> -	u64 *pte3;
> -	u64 *pte4;
> -
> -	if (!is_in_protected_mode(vcpu))
> -		return;
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> -		die("KVM_GET_SREGS failed");
> -
> -	pte4	= guest_flat_to_host(vcpu->kvm, vcpu->sregs.cr3);
> -	if (!host_ptr_in_ram(vcpu->kvm, pte4))
> -		return;
> -
> -	pte3	= guest_flat_to_host(vcpu->kvm, (*pte4 & ~0xfff));
> -	if (!host_ptr_in_ram(vcpu->kvm, pte3))
> -		return;
> -
> -	pte2	= guest_flat_to_host(vcpu->kvm, (*pte3 & ~0xfff));
> -	if (!host_ptr_in_ram(vcpu->kvm, pte2))
> -		return;
> -
> -	pte1	= guest_flat_to_host(vcpu->kvm, (*pte2 & ~0xfff));
> -	if (!host_ptr_in_ram(vcpu->kvm, pte1))
> -		return;
> -
> -	dprintf(debug_fd, "Page Tables:\n");
> -	if (*pte2 & (1 << 7))
> -		dprintf(debug_fd, " pte4: %016llx   pte3: %016llx"
> -			"   pte2: %016llx\n",
> -			*pte4, *pte3, *pte2);
> -	else
> -		dprintf(debug_fd, " pte4: %016llx  pte3: %016llx   pte2: %016"
> -			"llx   pte1: %016llx\n",
> -			*pte4, *pte3, *pte2, *pte1);
> -}
> -
>  void kvm_cpu__run(struct kvm_cpu *vcpu)
>  {
>  	int err;
> @@ -454,7 +83,6 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
>  	signal(SIGKVMEXIT, kvm_cpu_signal_handler);
>  	signal(SIGKVMPAUSE, kvm_cpu_signal_handler);
>  
> -	kvm_cpu__setup_cpuid(cpu);
>  	kvm_cpu__reset_vcpu(cpu);
>  
>  	if (cpu->kvm->single_step)
> diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
> index 252bd18..7ce1640 100644
> --- a/tools/kvm/kvm.c
> +++ b/tools/kvm/kvm.c
> @@ -1,10 +1,5 @@
>  #include "kvm/kvm.h"
> -
> -#include "kvm/boot-protocol.h"
> -#include "kvm/cpufeature.h"
>  #include "kvm/read-write.h"
> -#include "kvm/interrupt.h"
> -#include "kvm/mptable.h"
>  #include "kvm/util.h"
>  #include "kvm/mutex.h"
>  #include "kvm/kvm-cpu.h"
> @@ -12,14 +7,11 @@
>  
>  #include <linux/kvm.h>
>  
> -#include <asm/bootparam.h>
> -
>  #include <sys/un.h>
>  #include <sys/types.h>
>  #include <sys/socket.h>
>  #include <sys/ioctl.h>
>  #include <sys/mman.h>
> -#include <sys/stat.h>
>  #include <stdbool.h>
>  #include <assert.h>
>  #include <limits.h>
> @@ -58,29 +50,11 @@ const char *kvm_exit_reasons[] = {
>  	DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTERNAL_ERROR),
>  };
>  
> -#define DEFINE_KVM_EXT(ext)		\
> -	.name = #ext,			\
> -	.code = ext
> -
> -struct {
> -	const char *name;
> -	int code;
> -} kvm_req_ext[] = {
> -	{ DEFINE_KVM_EXT(KVM_CAP_COALESCED_MMIO) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_SET_TSS_ADDR) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_PIT2) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_USER_MEMORY) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_ROUTING) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_HLT) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_INJECT_STATUS) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_EXT_CPUID) },
> -};
> -
>  extern struct kvm *kvm;
>  extern struct kvm_cpu *kvm_cpus[KVM_NR_CPUS];
>  static int pause_event;
>  static DEFINE_MUTEX(pause_lock);
> +extern struct kvm_ext kvm_req_ext[];
>  
>  static char kvm_dir[PATH_MAX];
>  
> @@ -127,7 +101,9 @@ static int kvm__check_extensions(struct kvm *kvm)
>  {
>  	unsigned int i;
>  
> -	for (i = 0; i < ARRAY_SIZE(kvm_req_ext); i++) {
> +	for (i = 0; ; i++) {
> +		if (!kvm_req_ext[i].name)
> +			break;
>  		if (!kvm__supports_extension(kvm, kvm_req_ext[i].code)) {
>  			pr_error("Unsuppored KVM extension detected: %s",
>  				kvm_req_ext[i].name);
> @@ -261,48 +237,6 @@ void kvm__delete(struct kvm *kvm)
>  	free(kvm);
>  }
>  
> -static bool kvm__cpu_supports_vm(void)
> -{
> -	struct cpuid_regs regs;
> -	u32 eax_base;
> -	int feature;
> -
> -	regs	= (struct cpuid_regs) {
> -		.eax		= 0x00,
> -	};
> -	host_cpuid(&regs);
> -
> -	switch (regs.ebx) {
> -	case CPUID_VENDOR_INTEL_1:
> -		eax_base	= 0x00;
> -		feature		= KVM__X86_FEATURE_VMX;
> -		break;
> -
> -	case CPUID_VENDOR_AMD_1:
> -		eax_base	= 0x80000000;
> -		feature		= KVM__X86_FEATURE_SVM;
> -		break;
> -
> -	default:
> -		return false;
> -	}
> -
> -	regs	= (struct cpuid_regs) {
> -		.eax		= eax_base,
> -	};
> -	host_cpuid(&regs);
> -
> -	if (regs.eax < eax_base + 0x01)
> -		return false;
> -
> -	regs	= (struct cpuid_regs) {
> -		.eax		= eax_base + 0x01
> -	};
> -	host_cpuid(&regs);
> -
> -	return regs.ecx & (1 << feature);
> -}
> -
>  /*
>   * Note: KVM_SET_USER_MEMORY_REGION assumes that we don't pass overlapping
>   * memory regions to it. Therefore, be careful if you use this function for
> @@ -325,47 +259,6 @@ void kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspac
>  		die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
>  }
>  
> -/*
> - * Allocating RAM size bigger than 4GB requires us to leave a gap
> - * in the RAM which is used for PCI MMIO, hotplug, and unconfigured
> - * devices (see documentation of e820_setup_gap() for details).
> - *
> - * If we're required to initialize RAM bigger than 4GB, we will create
> - * a gap between 0xe0000000 and 0x100000000 in the guest virtual mem space.
> - */
> -
> -void kvm__init_ram(struct kvm *kvm)
> -{
> -	u64	phys_start, phys_size;
> -	void	*host_mem;
> -
> -	if (kvm->ram_size < KVM_32BIT_GAP_START) {
> -		/* Use a single block of RAM for 32bit RAM */
> -
> -		phys_start = 0;
> -		phys_size  = kvm->ram_size;
> -		host_mem   = kvm->ram_start;
> -
> -		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> -	} else {
> -		/* First RAM range from zero to the PCI gap: */
> -
> -		phys_start = 0;
> -		phys_size  = KVM_32BIT_GAP_START;
> -		host_mem   = kvm->ram_start;
> -
> -		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> -
> -		/* Second RAM range from 4GB to the end of RAM: */
> -
> -		phys_start = 0x100000000ULL;
> -		phys_size  = kvm->ram_size - phys_size;
> -		host_mem   = kvm->ram_start + phys_start;
> -
> -		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> -	}
> -}
> -
>  int kvm__recommended_cpus(struct kvm *kvm)
>  {
>  	int ret;
> @@ -410,11 +303,10 @@ int kvm__max_cpus(struct kvm *kvm)
>  
>  struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
>  {
> -	struct kvm_pit_config pit_config = { .flags = 0, };
>  	struct kvm *kvm;
>  	int ret;
>  
> -	if (!kvm__cpu_supports_vm())
> +	if (!kvm__arch_cpu_supports_vm())
>  		die("Your CPU does not support hardware virtualization");
>  
>  	kvm = kvm__new();
> @@ -442,36 +334,7 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
>  	if (kvm__check_extensions(kvm))
>  		die("A required KVM extention is not supported by OS");
>  
> -	ret = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
> -	if (ret < 0)
> -		die_perror("KVM_SET_TSS_ADDR ioctl");
> -
> -	ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config);
> -	if (ret < 0)
> -		die_perror("KVM_CREATE_PIT2 ioctl");
> -
> -	kvm->ram_size		= ram_size;
> -
> -	if (kvm->ram_size < KVM_32BIT_GAP_START) {
> -		kvm->ram_start = mmap(NULL, ram_size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
> -	} else {
> -		kvm->ram_start = mmap(NULL, ram_size + KVM_32BIT_GAP_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
> -		if (kvm->ram_start != MAP_FAILED) {
> -			/*
> -			 * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
> -			 * if we accidently write to it, we will know.
> -			 */
> -			mprotect(kvm->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
> -		}
> -	}
> -	if (kvm->ram_start = MAP_FAILED)
> -		die("out of memory");
> -
> -	madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
> -
> -	ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
> -	if (ret < 0)
> -		die_perror("KVM_CREATE_IRQCHIP ioctl");
> +	kvm__arch_init(kvm, kvm_dev, ram_size, name);
>  
>  	kvm->name = name;
>  
> @@ -480,141 +343,6 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
>  	return kvm;
>  }
>  
> -#define BOOT_LOADER_SELECTOR	0x1000
> -#define BOOT_LOADER_IP		0x0000
> -#define BOOT_LOADER_SP		0x8000
> -#define BOOT_CMDLINE_OFFSET	0x20000
> -
> -#define BOOT_PROTOCOL_REQUIRED	0x206
> -#define LOAD_HIGH		0x01
> -
> -static int load_flat_binary(struct kvm *kvm, int fd)
> -{
> -	void *p;
> -	int nr;
> -
> -	if (lseek(fd, 0, SEEK_SET) < 0)
> -		die_perror("lseek");
> -
> -	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
> -
> -	while ((nr = read(fd, p, 65536)) > 0)
> -		p += nr;
> -
> -	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
> -	kvm->boot_ip		= BOOT_LOADER_IP;
> -	kvm->boot_sp		= BOOT_LOADER_SP;
> -
> -	return true;
> -}
> -
> -static const char *BZIMAGE_MAGIC	= "HdrS";
> -
> -static bool load_bzimage(struct kvm *kvm, int fd_kernel,
> -			int fd_initrd, const char *kernel_cmdline, u16 vidmode)
> -{
> -	struct boot_params *kern_boot;
> -	unsigned long setup_sects;
> -	struct boot_params boot;
> -	size_t cmdline_size;
> -	ssize_t setup_size;
> -	void *p;
> -	int nr;
> -
> -	/*
> -	 * See Documentation/x86/boot.txt for details no bzImage on-disk and
> -	 * memory layout.
> -	 */
> -
> -	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> -		die_perror("lseek");
> -
> -	if (read(fd_kernel, &boot, sizeof(boot)) != sizeof(boot))
> -		return false;
> -
> -	if (memcmp(&boot.hdr.header, BZIMAGE_MAGIC, strlen(BZIMAGE_MAGIC)))
> -		return false;
> -
> -	if (boot.hdr.version < BOOT_PROTOCOL_REQUIRED)
> -		die("Too old kernel");
> -
> -	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> -		die_perror("lseek");
> -
> -	if (!boot.hdr.setup_sects)
> -		boot.hdr.setup_sects = BZ_DEFAULT_SETUP_SECTS;
> -	setup_sects = boot.hdr.setup_sects + 1;
> -
> -	setup_size = setup_sects << 9;
> -	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
> -
> -	/* copy setup.bin to mem*/
> -	if (read(fd_kernel, p, setup_size) != setup_size)
> -		die_perror("read");
> -
> -	/* copy vmlinux.bin to BZ_KERNEL_START*/
> -	p = guest_flat_to_host(kvm, BZ_KERNEL_START);
> -
> -	while ((nr = read(fd_kernel, p, 65536)) > 0)
> -		p += nr;
> -
> -	p = guest_flat_to_host(kvm, BOOT_CMDLINE_OFFSET);
> -	if (kernel_cmdline) {
> -		cmdline_size = strlen(kernel_cmdline) + 1;
> -		if (cmdline_size > boot.hdr.cmdline_size)
> -			cmdline_size = boot.hdr.cmdline_size;
> -
> -		memset(p, 0, boot.hdr.cmdline_size);
> -		memcpy(p, kernel_cmdline, cmdline_size - 1);
> -	}
> -
> -	kern_boot	= guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, 0x00);
> -
> -	kern_boot->hdr.cmd_line_ptr	= BOOT_CMDLINE_OFFSET;
> -	kern_boot->hdr.type_of_loader	= 0xff;
> -	kern_boot->hdr.heap_end_ptr	= 0xfe00;
> -	kern_boot->hdr.loadflags	|= CAN_USE_HEAP;
> -	kern_boot->hdr.vid_mode		= vidmode;
> -
> -	/*
> -	 * Read initrd image into guest memory
> -	 */
> -	if (fd_initrd >= 0) {
> -		struct stat initrd_stat;
> -		unsigned long addr;
> -
> -		if (fstat(fd_initrd, &initrd_stat))
> -			die_perror("fstat");
> -
> -		addr = boot.hdr.initrd_addr_max & ~0xfffff;
> -		for (;;) {
> -			if (addr < BZ_KERNEL_START)
> -				die("Not enough memory for initrd");
> -			else if (addr < (kvm->ram_size - initrd_stat.st_size))
> -				break;
> -			addr -= 0x100000;
> -		}
> -
> -		p = guest_flat_to_host(kvm, addr);
> -		nr = read(fd_initrd, p, initrd_stat.st_size);
> -		if (nr != initrd_stat.st_size)
> -			die("Failed to read initrd");
> -
> -		kern_boot->hdr.ramdisk_image	= addr;
> -		kern_boot->hdr.ramdisk_size	= initrd_stat.st_size;
> -	}
> -
> -	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
> -	/*
> -	 * The real-mode setup code starts at offset 0x200 of a bzImage. See
> -	 * Documentation/x86/boot.txt for details.
> -	 */
> -	kvm->boot_ip		= BOOT_LOADER_IP + 0x200;
> -	kvm->boot_sp		= BOOT_LOADER_SP;
> -
> -	return true;
> -}
> -
>  /* RFC 1952 */
>  #define GZIP_ID1		0x1f
>  #define GZIP_ID2		0x8b
> @@ -675,24 +403,6 @@ found_kernel:
>  	return ret;
>  }
>  
> -/**
> - * kvm__setup_bios - inject BIOS into guest system memory
> - * @kvm - guest system descriptor
> - *
> - * This function is a main routine where we poke guest memory
> - * and install BIOS there.
> - */
> -void kvm__setup_bios(struct kvm *kvm)
> -{
> -	/* standart minimal configuration */
> -	setup_bios(kvm);
> -
> -	/* FIXME: SMP, ACPI and friends here */
> -
> -	/* MP table */
> -	mptable_setup(kvm, kvm->nrcpus);
> -}
> -
>  #define TIMER_INTERVAL_NS 1000000	/* 1 msec */
>  
>  /*
> @@ -732,27 +442,6 @@ void kvm__stop_timer(struct kvm *kvm)
>  	kvm->timerid = 0;
>  }
>  
> -void kvm__irq_line(struct kvm *kvm, int irq, int level)
> -{
> -	struct kvm_irq_level irq_level;
> -
> -	irq_level	= (struct kvm_irq_level) {
> -		{
> -			.irq		= irq,
> -		},
> -		.level		= level,
> -	};
> -
> -	if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
> -		die_perror("KVM_IRQ_LINE failed");
> -}
> -
> -void kvm__irq_trigger(struct kvm *kvm, int irq)
> -{
> -	kvm__irq_line(kvm, irq, 1);
> -	kvm__irq_line(kvm, irq, 0);
> -}
> -
>  void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size)
>  {
>  	unsigned char *p;
> diff --git a/tools/kvm/bios.c b/tools/kvm/x86/bios.c
> similarity index 100%
> rename from tools/kvm/bios.c
> rename to tools/kvm/x86/bios.c
> diff --git a/tools/kvm/bios/.gitignore b/tools/kvm/x86/bios/.gitignore
> similarity index 100%
> rename from tools/kvm/bios/.gitignore
> rename to tools/kvm/x86/bios/.gitignore
> diff --git a/tools/kvm/bios/bios-rom.S b/tools/kvm/x86/bios/bios-rom.S
> similarity index 80%
> rename from tools/kvm/bios/bios-rom.S
> rename to tools/kvm/x86/bios/bios-rom.S
> index dc52b1e..3269ce9 100644
> --- a/tools/kvm/bios/bios-rom.S
> +++ b/tools/kvm/x86/bios/bios-rom.S
> @@ -8,5 +8,5 @@
>  #endif
>  
>  GLOBAL(bios_rom)
> -	.incbin "bios/bios.bin"
> +	.incbin "x86/bios/bios.bin"
>  END(bios_rom)
> diff --git a/tools/kvm/bios/e820.c b/tools/kvm/x86/bios/e820.c
> similarity index 100%
> rename from tools/kvm/bios/e820.c
> rename to tools/kvm/x86/bios/e820.c
> diff --git a/tools/kvm/bios/entry.S b/tools/kvm/x86/bios/entry.S
> similarity index 100%
> rename from tools/kvm/bios/entry.S
> rename to tools/kvm/x86/bios/entry.S
> diff --git a/tools/kvm/bios/gen-offsets.sh b/tools/kvm/x86/bios/gen-offsets.sh
> similarity index 100%
> rename from tools/kvm/bios/gen-offsets.sh
> rename to tools/kvm/x86/bios/gen-offsets.sh
> diff --git a/tools/kvm/bios/int10.c b/tools/kvm/x86/bios/int10.c
> similarity index 100%
> rename from tools/kvm/bios/int10.c
> rename to tools/kvm/x86/bios/int10.c
> diff --git a/tools/kvm/bios/int15.c b/tools/kvm/x86/bios/int15.c
> similarity index 100%
> rename from tools/kvm/bios/int15.c
> rename to tools/kvm/x86/bios/int15.c
> diff --git a/tools/kvm/bios/local.S b/tools/kvm/x86/bios/local.S
> similarity index 100%
> rename from tools/kvm/bios/local.S
> rename to tools/kvm/x86/bios/local.S
> diff --git a/tools/kvm/bios/macro.S b/tools/kvm/x86/bios/macro.S
> similarity index 100%
> rename from tools/kvm/bios/macro.S
> rename to tools/kvm/x86/bios/macro.S
> diff --git a/tools/kvm/bios/memcpy.c b/tools/kvm/x86/bios/memcpy.c
> similarity index 100%
> rename from tools/kvm/bios/memcpy.c
> rename to tools/kvm/x86/bios/memcpy.c
> diff --git a/tools/kvm/bios/rom.ld.S b/tools/kvm/x86/bios/rom.ld.S
> similarity index 100%
> rename from tools/kvm/bios/rom.ld.S
> rename to tools/kvm/x86/bios/rom.ld.S
> diff --git a/tools/kvm/cpuid.c b/tools/kvm/x86/cpuid.c
> similarity index 100%
> rename from tools/kvm/cpuid.c
> rename to tools/kvm/x86/cpuid.c
> diff --git a/tools/kvm/include/kvm/assembly.h b/tools/kvm/x86/include/kvm/assembly.h
> similarity index 100%
> rename from tools/kvm/include/kvm/assembly.h
> rename to tools/kvm/x86/include/kvm/assembly.h
> diff --git a/tools/kvm/include/kvm/barrier.h b/tools/kvm/x86/include/kvm/barrier.h
> similarity index 100%
> rename from tools/kvm/include/kvm/barrier.h
> rename to tools/kvm/x86/include/kvm/barrier.h
> diff --git a/tools/kvm/include/kvm/bios-export.h b/tools/kvm/x86/include/kvm/bios-export.h
> similarity index 100%
> rename from tools/kvm/include/kvm/bios-export.h
> rename to tools/kvm/x86/include/kvm/bios-export.h
> diff --git a/tools/kvm/include/kvm/bios.h b/tools/kvm/x86/include/kvm/bios.h
> similarity index 100%
> rename from tools/kvm/include/kvm/bios.h
> rename to tools/kvm/x86/include/kvm/bios.h
> diff --git a/tools/kvm/include/kvm/boot-protocol.h b/tools/kvm/x86/include/kvm/boot-protocol.h
> similarity index 100%
> rename from tools/kvm/include/kvm/boot-protocol.h
> rename to tools/kvm/x86/include/kvm/boot-protocol.h
> diff --git a/tools/kvm/include/kvm/cpufeature.h b/tools/kvm/x86/include/kvm/cpufeature.h
> similarity index 100%
> rename from tools/kvm/include/kvm/cpufeature.h
> rename to tools/kvm/x86/include/kvm/cpufeature.h
> diff --git a/tools/kvm/include/kvm/interrupt.h b/tools/kvm/x86/include/kvm/interrupt.h
> similarity index 100%
> rename from tools/kvm/include/kvm/interrupt.h
> rename to tools/kvm/x86/include/kvm/interrupt.h
> diff --git a/tools/kvm/x86/include/kvm/kvm-arch.h b/tools/kvm/x86/include/kvm/kvm-arch.h
> new file mode 100644
> index 0000000..02aa8b9
> --- /dev/null
> +++ b/tools/kvm/x86/include/kvm/kvm-arch.h
> @@ -0,0 +1,59 @@
> +#ifndef KVM__KVM_ARCH_H
> +#define KVM__KVM_ARCH_H
> +
> +#include "kvm/interrupt.h"
> +#include "kvm/segment.h"
> +
> +#include <stdbool.h>
> +#include <linux/types.h>
> +#include <time.h>
> +
> +#define KVM_NR_CPUS		(255)
> +
> +/*
> + * The hole includes VESA framebuffer and PCI memory.
> + */
> +#define KVM_32BIT_GAP_SIZE	(768 << 20)
> +#define KVM_32BIT_GAP_START	((1ULL << 32) - KVM_32BIT_GAP_SIZE)
> +
> +#define KVM_MMIO_START		KVM_32BIT_GAP_START
> +
> +struct kvm {
> +	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
> +	int			vm_fd;		/* For VM ioctls() */
> +	timer_t			timerid;	/* Posix timer for interrupts */
> +
> +	int			nrcpus;		/* Number of cpus to run */
> +
> +	u32			mem_slots;	/* for KVM_SET_USER_MEMORY_REGION */
> +
> +	u64			ram_size;
> +	void			*ram_start;
> +
> +	bool			nmi_disabled;
> +
> +	bool			single_step;
> +
> +	u16			boot_selector;
> +	u16			boot_ip;
> +	u16			boot_sp;
> +
> +	struct interrupt_table	interrupt_table;
> +
> +	const char		*vmlinux;
> +	struct disk_image       **disks;
> +	int                     nr_disks;
> +
> +	const char		*name;
> +};
> +
> +static inline void *guest_flat_to_host(struct kvm *kvm, unsigned long offset); /* In kvm.h */
> +
> +static inline void *guest_real_to_host(struct kvm *kvm, u16 selector, u16 offset)
> +{
> +	unsigned long flat = segment_to_flat(selector, offset);
> +
> +	return guest_flat_to_host(kvm, flat);
> +}
> +
> +#endif /* KVM__KVM_ARCH_H */
> diff --git a/tools/kvm/x86/include/kvm/kvm-cpu-arch.h b/tools/kvm/x86/include/kvm/kvm-cpu-arch.h
> new file mode 100644
> index 0000000..ed1c727
> --- /dev/null
> +++ b/tools/kvm/x86/include/kvm/kvm-cpu-arch.h
> @@ -0,0 +1,33 @@
> +#ifndef KVM__KVM_CPU_ARCH_H
> +#define KVM__KVM_CPU_ARCH_H
> +
> +/* Architecture-specific kvm_cpu definitions. */
> +
> +#include <linux/kvm.h>	/* for struct kvm_regs */
> +
> +#include <pthread.h>
> +
> +struct kvm;
> +
> +struct kvm_cpu {
> +	pthread_t		thread;		/* VCPU thread */
> +
> +	unsigned long		cpu_id;
> +
> +	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 */
> +
> +	u8			is_running;
> +	u8			paused;
> +
> +	struct kvm_coalesced_mmio_ring	*ring;
> +};
> +
> +#endif /* KVM__KVM_CPU_ARCH_H */
> diff --git a/tools/kvm/include/kvm/mptable.h b/tools/kvm/x86/include/kvm/mptable.h
> similarity index 100%
> rename from tools/kvm/include/kvm/mptable.h
> rename to tools/kvm/x86/include/kvm/mptable.h
> diff --git a/tools/kvm/interrupt.c b/tools/kvm/x86/interrupt.c
> similarity index 100%
> rename from tools/kvm/interrupt.c
> rename to tools/kvm/x86/interrupt.c
> diff --git a/tools/kvm/x86/ioport.c b/tools/kvm/x86/ioport.c
> new file mode 100644
> index 0000000..8a91bf2
> --- /dev/null
> +++ b/tools/kvm/x86/ioport.c
> @@ -0,0 +1,59 @@
> +#include "kvm/ioport.h"
> +
> +#include <stdlib.h>
> +
> +static bool debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> +{
> +	exit(EXIT_SUCCESS);
> +}
> +
> +static struct ioport_operations debug_ops = {
> +	.io_out		= debug_io_out,
> +};
> +
> +static bool dummy_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> +{
> +	return true;
> +}
> +
> +static bool dummy_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> +{
> +	return true;
> +}
> +
> +static struct ioport_operations dummy_read_write_ioport_ops = {
> +	.io_in		= dummy_io_in,
> +	.io_out		= dummy_io_out,
> +};
> +
> +static struct ioport_operations dummy_write_only_ioport_ops = {
> +	.io_out		= dummy_io_out,
> +};
> +
> +void ioport__setup_arch(void)
> +{
> +	/* Legacy ioport setup */
> +
> +	/* 0x0020 - 0x003F - 8259A PIC 1 */
> +	ioport__register(0x0020, &dummy_read_write_ioport_ops, 2, NULL);
> +
> +	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
> +	ioport__register(0x0040, &dummy_read_write_ioport_ops, 4, NULL);
> +
> +	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
> +	ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
> +
> +	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
> +	   internal debugging purposes.  */
> +	ioport__register(IOPORT_DBG, &debug_ops, 1, NULL);
> +
> +	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
> +	ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
> +
> +	/* 0x00F0 - 0x00FF - Math co-processor */
> +	ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
> +
> +	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
> +	ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
> +	ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
> +}
> diff --git a/tools/kvm/irq.c b/tools/kvm/x86/irq.c
> similarity index 100%
> rename from tools/kvm/irq.c
> rename to tools/kvm/x86/irq.c
> diff --git a/tools/kvm/x86/kvm-cpu.c b/tools/kvm/x86/kvm-cpu.c
> new file mode 100644
> index 0000000..b26b208
> --- /dev/null
> +++ b/tools/kvm/x86/kvm-cpu.c
> @@ -0,0 +1,383 @@
> +#include "kvm/kvm-cpu.h"
> +
> +#include "kvm/symbol.h"
> +#include "kvm/util.h"
> +#include "kvm/kvm.h"
> +
> +#include <asm/msr-index.h>
> +
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <signal.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <stdio.h>
> +
> +static int debug_fd;
> +
> +void kvm_cpu__set_debug_fd(int fd)
> +{
> +	debug_fd = fd;
> +}
> +
> +int kvm_cpu__get_debug_fd(void)
> +{
> +	return debug_fd;
> +}
> +
> +static inline bool is_in_protected_mode(struct kvm_cpu *vcpu)
> +{
> +	return vcpu->sregs.cr0 & 0x01;
> +}
> +
> +static inline u64 ip_to_flat(struct kvm_cpu *vcpu, u64 ip)
> +{
> +	u64 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(vcpu))
> +		return ip;
> +
> +	cs = vcpu->sregs.cs.selector;
> +
> +	return ip + (cs << 4);
> +}
> +
> +static inline u32 selector_to_base(u16 selector)
> +{
> +	/*
> +	 * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
> +	 */
> +	return (u32)selector * 16;
> +}
> +
> +static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
> +{
> +	struct kvm_cpu *vcpu;
> +
> +	vcpu		= calloc(1, sizeof *vcpu);
> +	if (!vcpu)
> +		return NULL;
> +
> +	vcpu->kvm	= kvm;
> +
> +	return vcpu;
> +}
> +
> +void kvm_cpu__delete(struct kvm_cpu *vcpu)
> +{
> +	if (vcpu->msrs)
> +		free(vcpu->msrs);
> +
> +	free(vcpu);
> +}
> +
> +struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id)
> +{
> +	struct kvm_cpu *vcpu;
> +	int mmap_size;
> +	int coalesced_offset;
> +
> +	vcpu		= kvm_cpu__new(kvm);
> +	if (!vcpu)
> +		return NULL;
> +
> +	vcpu->cpu_id	= cpu_id;
> +
> +	vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
> +	if (vcpu->vcpu_fd < 0)
> +		die_perror("KVM_CREATE_VCPU ioctl");
> +
> +	mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
> +	if (mmap_size < 0)
> +		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
> +
> +	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
> +	if (vcpu->kvm_run = MAP_FAILED)
> +		die("unable to mmap vcpu fd");
> +
> +	coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
> +	if (coalesced_offset)
> +		vcpu->ring = (void *)vcpu->kvm_run + (coalesced_offset * PAGE_SIZE);
> +
> +	vcpu->is_running = true;
> +
> +	return vcpu;
> +}
> +
> +static struct kvm_msrs *kvm_msrs__new(size_t nmsrs)
> +{
> +	struct kvm_msrs *vcpu = calloc(1, sizeof(*vcpu) + (sizeof(struct kvm_msr_entry) * nmsrs));
> +
> +	if (!vcpu)
> +		die("out of memory");
> +
> +	return vcpu;
> +}
> +
> +#define KVM_MSR_ENTRY(_index, _data)	\
> +	(struct kvm_msr_entry) { .index = _index, .data = _data }
> +
> +static void kvm_cpu__setup_msrs(struct kvm_cpu *vcpu)
> +{
> +	unsigned long ndx = 0;
> +
> +	vcpu->msrs = kvm_msrs__new(100);
> +
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_CS,	0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_ESP,	0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_EIP,	0x0);
> +#ifdef CONFIG_X86_64
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_STAR,			0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_CSTAR,			0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_KERNEL_GS_BASE,		0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_SYSCALL_MASK,		0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_LSTAR,			0x0);
> +#endif
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_TSC,		0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_MISC_ENABLE,
> +						MSR_IA32_MISC_ENABLE_FAST_STRING);
> +
> +	vcpu->msrs->nmsrs	= ndx;
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_SET_MSRS, vcpu->msrs) < 0)
> +		die_perror("KVM_SET_MSRS failed");
> +}
> +
> +static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
> +{
> +	vcpu->fpu = (struct kvm_fpu) {
> +		.fcw		= 0x37f,
> +		.mxcsr		= 0x1f80,
> +	};
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_SET_FPU, &vcpu->fpu) < 0)
> +		die_perror("KVM_SET_FPU failed");
> +}
> +
> +static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
> +{
> +	vcpu->regs = (struct kvm_regs) {
> +		/* We start the guest in 16-bit real mode  */
> +		.rflags		= 0x0000000000000002ULL,
> +
> +		.rip		= vcpu->kvm->boot_ip,
> +		.rsp		= vcpu->kvm->boot_sp,
> +		.rbp		= vcpu->kvm->boot_sp,
> +	};
> +
> +	if (vcpu->regs.rip > USHRT_MAX)
> +		die("ip 0x%llx is too high for real mode", (u64) vcpu->regs.rip);
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
> +		die_perror("KVM_SET_REGS failed");
> +}
> +
> +static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
> +{
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> +		die_perror("KVM_GET_SREGS failed");
> +
> +	vcpu->sregs.cs.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.cs.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.ss.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.ss.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.ds.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.ds.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.es.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.es.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.fs.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.fs.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.gs.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.gs.base	= selector_to_base(vcpu->kvm->boot_selector);
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_SET_SREGS, &vcpu->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 *vcpu)
> +{
> +	kvm_cpu__setup_cpuid(vcpu);
> +	kvm_cpu__setup_sregs(vcpu);
> +	kvm_cpu__setup_regs(vcpu);
> +	kvm_cpu__setup_fpu(vcpu);
> +	kvm_cpu__setup_msrs(vcpu);
> +}
> +
> +static void print_dtable(const char *name, struct kvm_dtable *dtable)
> +{
> +	dprintf(debug_fd, " %s                 %016llx  %08hx\n",
> +		name, (u64) dtable->base, (u16) dtable->limit);
> +}
> +
> +static void print_segment(const char *name, struct kvm_segment *seg)
> +{
> +	dprintf(debug_fd, " %s       %04hx      %016llx  %08x  %02hhx    %x %x   %x  %x %x %x %x\n",
> +		name, (u16) seg->selector, (u64) seg->base, (u32) seg->limit,
> +		(u8) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
> +}
> +
> +void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
> +{
> +	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(vcpu->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;
> +
> +	dprintf(debug_fd, "\n Registers:\n");
> +	dprintf(debug_fd,   " ----------\n");
> +	dprintf(debug_fd, " rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
> +	dprintf(debug_fd, " rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
> +	dprintf(debug_fd, " rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
> +	dprintf(debug_fd, " rbp: %016lx    r8: %016lx    r9: %016lx\n", rbp, r8,  r9);
> +	dprintf(debug_fd, " r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
> +	dprintf(debug_fd, " r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
> +
> +	if (ioctl(vcpu->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;
> +
> +	dprintf(debug_fd, " cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
> +	dprintf(debug_fd, " cr4: %016lx   cr8: %016lx\n", cr4, cr8);
> +	dprintf(debug_fd, "\n Segment registers:\n");
> +	dprintf(debug_fd,   " ------------------\n");
> +	dprintf(debug_fd, " 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);
> +
> +	dprintf(debug_fd, "\n APIC:\n");
> +	dprintf(debug_fd,   " -----\n");
> +	dprintf(debug_fd, " efer: %016llx  apic base: %016llx  nmi: %s\n",
> +		(u64) sregs.efer, (u64) sregs.apic_base,
> +		(vcpu->kvm->nmi_disabled ? "disabled" : "enabled"));
> +
> +	dprintf(debug_fd, "\n Interrupt bitmap:\n");
> +	dprintf(debug_fd,   " -----------------\n");
> +	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
> +		dprintf(debug_fd, " %016llx", (u64) sregs.interrupt_bitmap[i]);
> +	dprintf(debug_fd, "\n");
> +}
> +
> +#define MAX_SYM_LEN		128
> +
> +void kvm_cpu__show_code(struct kvm_cpu *vcpu)
> +{
> +	unsigned int code_bytes = 64;
> +	unsigned int code_prologue = code_bytes * 43 / 64;
> +	unsigned int code_len = code_bytes;
> +	char sym[MAX_SYM_LEN];
> +	unsigned char c;
> +	unsigned int i;
> +	u8 *ip;
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
> +		die("KVM_GET_REGS failed");
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> +		die("KVM_GET_SREGS failed");
> +
> +	ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip) - code_prologue);
> +
> +	dprintf(debug_fd, "\n Code:\n");
> +	dprintf(debug_fd,   " -----\n");
> +
> +	symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
> +
> +	dprintf(debug_fd, " rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
> +
> +	for (i = 0; i < code_len; i++, ip++) {
> +		if (!host_ptr_in_ram(vcpu->kvm, ip))
> +			break;
> +
> +		c = *ip;
> +
> +		if (ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip)))
> +			dprintf(debug_fd, " <%02x>", c);
> +		else
> +			dprintf(debug_fd, " %02x", c);
> +	}
> +
> +	dprintf(debug_fd, "\n");
> +
> +	dprintf(debug_fd, "\n Stack:\n");
> +	dprintf(debug_fd,   " ------\n");
> +	kvm__dump_mem(vcpu->kvm, vcpu->regs.rsp, 32);
> +}
> +
> +void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
> +{
> +	u64 *pte1;
> +	u64 *pte2;
> +	u64 *pte3;
> +	u64 *pte4;
> +
> +	if (!is_in_protected_mode(vcpu))
> +		return;
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> +		die("KVM_GET_SREGS failed");
> +
> +	pte4	= guest_flat_to_host(vcpu->kvm, vcpu->sregs.cr3);
> +	if (!host_ptr_in_ram(vcpu->kvm, pte4))
> +		return;
> +
> +	pte3	= guest_flat_to_host(vcpu->kvm, (*pte4 & ~0xfff));
> +	if (!host_ptr_in_ram(vcpu->kvm, pte3))
> +		return;
> +
> +	pte2	= guest_flat_to_host(vcpu->kvm, (*pte3 & ~0xfff));
> +	if (!host_ptr_in_ram(vcpu->kvm, pte2))
> +		return;
> +
> +	pte1	= guest_flat_to_host(vcpu->kvm, (*pte2 & ~0xfff));
> +	if (!host_ptr_in_ram(vcpu->kvm, pte1))
> +		return;
> +
> +	dprintf(debug_fd, "Page Tables:\n");
> +	if (*pte2 & (1 << 7))
> +		dprintf(debug_fd, " pte4: %016llx   pte3: %016llx"
> +			"   pte2: %016llx\n",
> +			*pte4, *pte3, *pte2);
> +	else
> +		dprintf(debug_fd, " pte4: %016llx  pte3: %016llx   pte2: %016"
> +			"llx   pte1: %016llx\n",
> +			*pte4, *pte3, *pte2, *pte1);
> +}
> diff --git a/tools/kvm/x86/kvm.c b/tools/kvm/x86/kvm.c
> new file mode 100644
> index 0000000..ac6c91e
> --- /dev/null
> +++ b/tools/kvm/x86/kvm.c
> @@ -0,0 +1,330 @@
> +#include "kvm/kvm.h"
> +#include "kvm/boot-protocol.h"
> +#include "kvm/cpufeature.h"
> +#include "kvm/interrupt.h"
> +#include "kvm/mptable.h"
> +#include "kvm/util.h"
> +
> +#include <asm/bootparam.h>
> +#include <linux/kvm.h>
> +
> +#include <sys/types.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <sys/stat.h>
> +#include <stdbool.h>
> +#include <assert.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <fcntl.h>
> +#include <asm/unistd.h>
> +
> +struct kvm_ext kvm_req_ext[] = {
> +	{ DEFINE_KVM_EXT(KVM_CAP_COALESCED_MMIO) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_SET_TSS_ADDR) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_PIT2) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_USER_MEMORY) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_ROUTING) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_HLT) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_INJECT_STATUS) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_EXT_CPUID) },
> +	{ 0, 0 }
> +};
> +
> +bool kvm__arch_cpu_supports_vm(void)
> +{
> +	struct cpuid_regs regs;
> +	u32 eax_base;
> +	int feature;
> +
> +	regs	= (struct cpuid_regs) {
> +		.eax		= 0x00,
> +	};
> +	host_cpuid(&regs);
> +
> +	switch (regs.ebx) {
> +	case CPUID_VENDOR_INTEL_1:
> +		eax_base	= 0x00;
> +		feature		= KVM__X86_FEATURE_VMX;
> +		break;
> +
> +	case CPUID_VENDOR_AMD_1:
> +		eax_base	= 0x80000000;
> +		feature		= KVM__X86_FEATURE_SVM;
> +		break;
> +
> +	default:
> +		return false;
> +	}
> +
> +	regs	= (struct cpuid_regs) {
> +		.eax		= eax_base,
> +	};
> +	host_cpuid(&regs);
> +
> +	if (regs.eax < eax_base + 0x01)
> +		return false;
> +
> +	regs	= (struct cpuid_regs) {
> +		.eax		= eax_base + 0x01
> +	};
> +	host_cpuid(&regs);
> +
> +	return regs.ecx & (1 << feature);
> +}
> +
> +/*
> + * Allocating RAM size bigger than 4GB requires us to leave a gap
> + * in the RAM which is used for PCI MMIO, hotplug, and unconfigured
> + * devices (see documentation of e820_setup_gap() for details).
> + *
> + * If we're required to initialize RAM bigger than 4GB, we will create
> + * a gap between 0xe0000000 and 0x100000000 in the guest virtual mem space.
> + */
> +
> +void kvm__init_ram(struct kvm *kvm)
> +{
> +	u64	phys_start, phys_size;
> +	void	*host_mem;
> +
> +	if (kvm->ram_size < KVM_32BIT_GAP_START) {
> +		/* Use a single block of RAM for 32bit RAM */
> +
> +		phys_start = 0;
> +		phys_size  = kvm->ram_size;
> +		host_mem   = kvm->ram_start;
> +
> +		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> +	} else {
> +		/* First RAM range from zero to the PCI gap: */
> +
> +		phys_start = 0;
> +		phys_size  = KVM_32BIT_GAP_START;
> +		host_mem   = kvm->ram_start;
> +
> +		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> +
> +		/* Second RAM range from 4GB to the end of RAM: */
> +
> +		phys_start = 0x100000000ULL;
> +		phys_size  = kvm->ram_size - phys_size;
> +		host_mem   = kvm->ram_start + phys_start;
> +
> +		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> +	}
> +}
> +
> +/* Architecture-specific KVM init */
> +void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name)
> +{
> +	struct kvm_pit_config pit_config = { .flags = 0, };
> +	int ret;
> +
> +	ret = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
> +	if (ret < 0)
> +		die_perror("KVM_SET_TSS_ADDR ioctl");
> +
> +	ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config);
> +	if (ret < 0)
> +		die_perror("KVM_CREATE_PIT2 ioctl");
> +
> +	kvm->ram_size		= ram_size;
> +
> +	if (kvm->ram_size < KVM_32BIT_GAP_START) {
> +		kvm->ram_start = mmap(NULL, ram_size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
> +	} else {
> +		kvm->ram_start = mmap(NULL, ram_size + KVM_32BIT_GAP_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
> +		if (kvm->ram_start != MAP_FAILED) {
> +			/*
> +			 * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
> +			 * if we accidently write to it, we will know.
> +			 */
> +			mprotect(kvm->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
> +		}
> +	}
> +	if (kvm->ram_start = MAP_FAILED)
> +		die("out of memory");
> +
> +	madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
> +
> +	ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
> +	if (ret < 0)
> +		die_perror("KVM_CREATE_IRQCHIP ioctl");
> +}
> +
> +void kvm__irq_line(struct kvm *kvm, int irq, int level)
> +{
> +	struct kvm_irq_level irq_level;
> +
> +	irq_level	= (struct kvm_irq_level) {
> +		{
> +			.irq		= irq,
> +		},
> +		.level		= level,
> +	};
> +
> +	if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
> +		die_perror("KVM_IRQ_LINE failed");
> +}
> +
> +void kvm__irq_trigger(struct kvm *kvm, int irq)
> +{
> +	kvm__irq_line(kvm, irq, 1);
> +	kvm__irq_line(kvm, irq, 0);
> +}
> +
> +#define BOOT_LOADER_SELECTOR	0x1000
> +#define BOOT_LOADER_IP		0x0000
> +#define BOOT_LOADER_SP		0x8000
> +#define BOOT_CMDLINE_OFFSET	0x20000
> +
> +#define BOOT_PROTOCOL_REQUIRED	0x206
> +#define LOAD_HIGH		0x01
> +
> +int load_flat_binary(struct kvm *kvm, int fd)
> +{
> +	void *p;
> +	int nr;
> +
> +	if (lseek(fd, 0, SEEK_SET) < 0)
> +		die_perror("lseek");
> +
> +	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
> +
> +	while ((nr = read(fd, p, 65536)) > 0)
> +		p += nr;
> +
> +	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
> +	kvm->boot_ip		= BOOT_LOADER_IP;
> +	kvm->boot_sp		= BOOT_LOADER_SP;
> +
> +	return true;
> +}
> +
> +static const char *BZIMAGE_MAGIC	= "HdrS";
> +
> +bool load_bzimage(struct kvm *kvm, int fd_kernel,
> +		  int fd_initrd, const char *kernel_cmdline, u16 vidmode)
> +{
> +	struct boot_params *kern_boot;
> +	unsigned long setup_sects;
> +	struct boot_params boot;
> +	size_t cmdline_size;
> +	ssize_t setup_size;
> +	void *p;
> +	int nr;
> +
> +	/*
> +	 * See Documentation/x86/boot.txt for details no bzImage on-disk and
> +	 * memory layout.
> +	 */
> +
> +	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> +		die_perror("lseek");
> +
> +	if (read(fd_kernel, &boot, sizeof(boot)) != sizeof(boot))
> +		return false;
> +
> +	if (memcmp(&boot.hdr.header, BZIMAGE_MAGIC, strlen(BZIMAGE_MAGIC)))
> +		return false;
> +
> +	if (boot.hdr.version < BOOT_PROTOCOL_REQUIRED)
> +		die("Too old kernel");
> +
> +	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> +		die_perror("lseek");
> +
> +	if (!boot.hdr.setup_sects)
> +		boot.hdr.setup_sects = BZ_DEFAULT_SETUP_SECTS;
> +	setup_sects = boot.hdr.setup_sects + 1;
> +
> +	setup_size = setup_sects << 9;
> +	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
> +
> +	/* copy setup.bin to mem*/
> +	if (read(fd_kernel, p, setup_size) != setup_size)
> +		die_perror("read");
> +
> +	/* copy vmlinux.bin to BZ_KERNEL_START*/
> +	p = guest_flat_to_host(kvm, BZ_KERNEL_START);
> +
> +	while ((nr = read(fd_kernel, p, 65536)) > 0)
> +		p += nr;
> +
> +	p = guest_flat_to_host(kvm, BOOT_CMDLINE_OFFSET);
> +	if (kernel_cmdline) {
> +		cmdline_size = strlen(kernel_cmdline) + 1;
> +		if (cmdline_size > boot.hdr.cmdline_size)
> +			cmdline_size = boot.hdr.cmdline_size;
> +
> +		memset(p, 0, boot.hdr.cmdline_size);
> +		memcpy(p, kernel_cmdline, cmdline_size - 1);
> +	}
> +
> +	kern_boot	= guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, 0x00);
> +
> +	kern_boot->hdr.cmd_line_ptr	= BOOT_CMDLINE_OFFSET;
> +	kern_boot->hdr.type_of_loader	= 0xff;
> +	kern_boot->hdr.heap_end_ptr	= 0xfe00;
> +	kern_boot->hdr.loadflags	|= CAN_USE_HEAP;
> +	kern_boot->hdr.vid_mode		= vidmode;
> +
> +	/*
> +	 * Read initrd image into guest memory
> +	 */
> +	if (fd_initrd >= 0) {
> +		struct stat initrd_stat;
> +		unsigned long addr;
> +
> +		if (fstat(fd_initrd, &initrd_stat))
> +			die_perror("fstat");
> +
> +		addr = boot.hdr.initrd_addr_max & ~0xfffff;
> +		for (;;) {
> +			if (addr < BZ_KERNEL_START)
> +				die("Not enough memory for initrd");
> +			else if (addr < (kvm->ram_size - initrd_stat.st_size))
> +				break;
> +			addr -= 0x100000;
> +		}
> +
> +		p = guest_flat_to_host(kvm, addr);
> +		nr = read(fd_initrd, p, initrd_stat.st_size);
> +		if (nr != initrd_stat.st_size)
> +			die("Failed to read initrd");
> +
> +		kern_boot->hdr.ramdisk_image	= addr;
> +		kern_boot->hdr.ramdisk_size	= initrd_stat.st_size;
> +	}
> +
> +	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
> +	/*
> +	 * The real-mode setup code starts at offset 0x200 of a bzImage. See
> +	 * Documentation/x86/boot.txt for details.
> +	 */
> +	kvm->boot_ip		= BOOT_LOADER_IP + 0x200;
> +	kvm->boot_sp		= BOOT_LOADER_SP;
> +
> +	return true;
> +}
> +
> +/**
> + * kvm__arch_setup_firmware - inject BIOS into guest system memory
> + * @kvm - guest system descriptor
> + *
> + * This function is a main routine where we poke guest memory
> + * and install BIOS there.
> + */
> +void kvm__arch_setup_firmware(struct kvm *kvm)
> +{
> +	/* standart minimal configuration */
> +	setup_bios(kvm);
> +
> +	/* FIXME: SMP, ACPI and friends here */
> +
> +	/* MP table */
> +	mptable_setup(kvm, kvm->nrcpus);
> +}
> diff --git a/tools/kvm/mptable.c b/tools/kvm/x86/mptable.c
> similarity index 100%
> rename from tools/kvm/mptable.c
> rename to tools/kvm/x86/mptable.c
> --
> 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

-- 

Sasha.


WARNING: multiple messages have this Message-ID (diff)
From: Sasha Levin <levinsasha928@gmail.com>
To: Matt Evans <matt@ozlabs.org>
Cc: kvm@vger.kernel.org, kvm-ppc@vger.kernel.org
Subject: Re: [PATCH 01/28] kvm tools: Split x86 arch-specific bits into x86/
Date: Tue, 06 Dec 2011 10:07:46 +0200	[thread overview]
Message-ID: <1323158866.3882.2.camel@lappy> (raw)
In-Reply-To: <4EDD8DED.3070908@ozlabs.org>

The code doesn't build after this patch due to missing header issues
which you fixed in patches #10 & #11. Could you please move those two to
the beginning of the series for the sake of bisectablilty?

On Tue, 2011-12-06 at 14:37 +1100, Matt Evans wrote:
> Create a new arch-specific subdirectory to contain architecture-specific code
> and includes.
> 
> The Makefile now adds various arch-specific objects based on detected
> architecture.  That aside, this patch should only contain code moves.  These
> include:
> 
> - x86-specific kvm_cpu setup, kernel loading, memory setup etc. now in
>   x86/kvm{-cpu}.c
> - BIOS now lives in x86/bios/
> - ioport setup
> - KVM extensions are asserted in arch-specific kvm.c now, so each architecture
>   can manage its own dependencies.
> - Various architecture-specific #defines are moved into $(ARCH)/include/kvm{-cpu}.h
>   such as struct kvm_cpu, KVM_NR_CPUS, KVM_32BIT_GAP_SIZE.
> 
> Signed-off-by: Matt Evans <matt@ozlabs.org>
> ---
>  tools/kvm/Makefile                              |   96 ++++---
>  tools/kvm/builtin-run.c                         |    6 +-
>  tools/kvm/include/kvm/ioport.h                  |    2 +-
>  tools/kvm/include/kvm/kvm-cpu.h                 |   27 +--
>  tools/kvm/include/kvm/kvm.h                     |   58 +---
>  tools/kvm/ioport.c                              |   54 ----
>  tools/kvm/kvm-cpu.c                             |  372 ----------------------
>  tools/kvm/kvm.c                                 |  323 +-------------------
>  tools/kvm/{ => x86}/bios.c                      |    0
>  tools/kvm/{ => x86}/bios/.gitignore             |    0
>  tools/kvm/{ => x86}/bios/bios-rom.S             |    2 +-
>  tools/kvm/{ => x86}/bios/e820.c                 |    0
>  tools/kvm/{ => x86}/bios/entry.S                |    0
>  tools/kvm/{ => x86}/bios/gen-offsets.sh         |    0
>  tools/kvm/{ => x86}/bios/int10.c                |    0
>  tools/kvm/{ => x86}/bios/int15.c                |    0
>  tools/kvm/{ => x86}/bios/local.S                |    0
>  tools/kvm/{ => x86}/bios/macro.S                |    0
>  tools/kvm/{ => x86}/bios/memcpy.c               |    0
>  tools/kvm/{ => x86}/bios/rom.ld.S               |    0
>  tools/kvm/{ => x86}/cpuid.c                     |    0
>  tools/kvm/{ => x86}/include/kvm/assembly.h      |    0
>  tools/kvm/{ => x86}/include/kvm/barrier.h       |    0
>  tools/kvm/{ => x86}/include/kvm/bios-export.h   |    0
>  tools/kvm/{ => x86}/include/kvm/bios.h          |    0
>  tools/kvm/{ => x86}/include/kvm/boot-protocol.h |    0
>  tools/kvm/{ => x86}/include/kvm/cpufeature.h    |    0
>  tools/kvm/{ => x86}/include/kvm/interrupt.h     |    0
>  tools/kvm/x86/include/kvm/kvm-arch.h            |   59 ++++
>  tools/kvm/x86/include/kvm/kvm-cpu-arch.h        |   33 ++
>  tools/kvm/{ => x86}/include/kvm/mptable.h       |    0
>  tools/kvm/{ => x86}/interrupt.c                 |    0
>  tools/kvm/x86/ioport.c                          |   59 ++++
>  tools/kvm/{ => x86}/irq.c                       |    0
>  tools/kvm/x86/kvm-cpu.c                         |  383 +++++++++++++++++++++++
>  tools/kvm/x86/kvm.c                             |  330 +++++++++++++++++++
>  tools/kvm/{ => x86}/mptable.c                   |    0
>  37 files changed, 951 insertions(+), 853 deletions(-)
>  rename tools/kvm/{ => x86}/bios.c (100%)
>  rename tools/kvm/{ => x86}/bios/.gitignore (100%)
>  rename tools/kvm/{ => x86}/bios/bios-rom.S (80%)
>  rename tools/kvm/{ => x86}/bios/e820.c (100%)
>  rename tools/kvm/{ => x86}/bios/entry.S (100%)
>  rename tools/kvm/{ => x86}/bios/gen-offsets.sh (100%)
>  rename tools/kvm/{ => x86}/bios/int10.c (100%)
>  rename tools/kvm/{ => x86}/bios/int15.c (100%)
>  rename tools/kvm/{ => x86}/bios/local.S (100%)
>  rename tools/kvm/{ => x86}/bios/macro.S (100%)
>  rename tools/kvm/{ => x86}/bios/memcpy.c (100%)
>  rename tools/kvm/{ => x86}/bios/rom.ld.S (100%)
>  rename tools/kvm/{ => x86}/cpuid.c (100%)
>  rename tools/kvm/{ => x86}/include/kvm/assembly.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/barrier.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/bios-export.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/bios.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/boot-protocol.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/cpufeature.h (100%)
>  rename tools/kvm/{ => x86}/include/kvm/interrupt.h (100%)
>  create mode 100644 tools/kvm/x86/include/kvm/kvm-arch.h
>  create mode 100644 tools/kvm/x86/include/kvm/kvm-cpu-arch.h
>  rename tools/kvm/{ => x86}/include/kvm/mptable.h (100%)
>  rename tools/kvm/{ => x86}/interrupt.c (100%)
>  create mode 100644 tools/kvm/x86/ioport.c
>  rename tools/kvm/{ => x86}/irq.c (100%)
>  create mode 100644 tools/kvm/x86/kvm-cpu.c
>  create mode 100644 tools/kvm/x86/kvm.c
>  rename tools/kvm/{ => x86}/mptable.c (100%)
> 
> diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
> index bb5f6b0..243886e 100644
> --- a/tools/kvm/Makefile
> +++ b/tools/kvm/Makefile
> @@ -33,13 +33,11 @@ OBJS	+= builtin-run.o
>  OBJS	+= builtin-setup.o
>  OBJS	+= builtin-stop.o
>  OBJS	+= builtin-version.o
> -OBJS	+= cpuid.o
>  OBJS	+= disk/core.o
>  OBJS	+= framebuffer.o
>  OBJS	+= guest_compat.o
>  OBJS	+= hw/rtc.o
>  OBJS	+= hw/serial.o
> -OBJS	+= interrupt.o
>  OBJS	+= ioport.o
>  OBJS	+= kvm-cpu.o
>  OBJS	+= kvm.o
> @@ -61,7 +59,6 @@ OBJS	+= disk/blk.o
>  OBJS	+= disk/qcow.o
>  OBJS	+= disk/raw.o
>  OBJS	+= ioeventfd.o
> -OBJS	+= irq.o
>  OBJS	+= net/uip/core.o
>  OBJS	+= net/uip/arp.o
>  OBJS	+= net/uip/icmp.o
> @@ -72,7 +69,6 @@ OBJS	+= net/uip/buf.o
>  OBJS	+= net/uip/csum.o
>  OBJS	+= net/uip/dhcp.o
>  OBJS	+= kvm-cmd.o
> -OBJS	+= mptable.o
>  OBJS	+= rbtree.o
>  OBJS	+= threadpool.o
>  OBJS	+= util/parse-options.o
> @@ -123,12 +119,6 @@ ifeq ($(has_AIO),y)
>  	LIBS	+= -laio
>  endif
>  
> -DEPS	:= $(patsubst %.o,%.d,$(OBJS))
> -
> -# Exclude BIOS object files from header dependencies.
> -OBJS	+= bios.o
> -OBJS	+= bios/bios-rom.o
> -
>  LIBS	+= -lrt
>  LIBS	+= -lpthread
>  LIBS	+= -lutil
> @@ -150,12 +140,43 @@ ifeq ($(uname_M),x86_64)
>  	DEFINES      += -DCONFIG_X86_64
>  endif
>  
> +
> +### Arch-specific stuff
> +
> +#x86
> +ifeq ($(ARCH),x86)
> +	DEFINES += -DCONFIG_X86
> +	OBJS	+= x86/cpuid.o
> +	OBJS	+= x86/interrupt.o
> +	OBJS	+= x86/ioport.o
> +	OBJS	+= x86/irq.o
> +	OBJS	+= x86/kvm.o
> +	OBJS	+= x86/kvm-cpu.o
> +	OBJS	+= x86/mptable.o
> +# Exclude BIOS object files from header dependencies.
> +	OTHEROBJS	+= x86/bios.o
> +	OTHEROBJS	+= x86/bios/bios-rom.o
> +	ARCH_INCLUDE := x86/include
> +endif
> +
> +###
> +
> +ifeq (,$(ARCH_INCLUDE))
> +	UNSUPP_ERR = @echo "This architecture is not supported in kvmtool." && exit 1
> +else
> +	UNSUPP_ERR =
> +endif
> +
> +DEPS	:= $(patsubst %.o,%.d,$(OBJS))
> +OBJS	+= $(OTHEROBJS)
> +
>  DEFINES	+= -D_FILE_OFFSET_BITS=64
>  DEFINES	+= -D_GNU_SOURCE
>  DEFINES	+= -DKVMTOOLS_VERSION='"$(KVMTOOLS_VERSION)"'
> +DEFINES	+= -DBUILD_ARCH='"$(ARCH)"'
>  
>  KVM_INCLUDE := include
> -CFLAGS	+= $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -Os -g
> +CFLAGS	+= $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I$(ARCH_INCLUDE) -I../../include -I../../arch/$(ARCH)/include/ -Os -g
>  
>  ifneq ($(WERROR),0)
>  	WARNINGS += -Werror
> @@ -179,7 +200,10 @@ WARNINGS += -Wwrite-strings
>  
>  CFLAGS	+= $(WARNINGS)
>  
> -all: $(PROGRAM) $(GUEST_INIT)
> +all: arch_support_check $(PROGRAM) $(GUEST_INIT)
> +
> +arch_support_check:
> +	$(UNSUPP_ERR)
>  
>  KVMTOOLS-VERSION-FILE:
>  	@$(SHELL_PATH) util/KVMTOOLS-VERSION-GEN $(OUTPUT)
> @@ -227,33 +251,33 @@ BIOS_CFLAGS += -mregparm=3
>  BIOS_CFLAGS += -fno-stack-protector
>  BIOS_CFLAGS += -I../../arch/$(ARCH)
>  
> -bios.o: bios/bios.bin bios/bios-rom.h
> -
> -bios/bios.bin.elf: bios/entry.S bios/e820.c bios/int10.c bios/int15.c bios/rom.ld.S
> -	$(E) "  CC       bios/memcpy.o"
> -	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/memcpy.c -o bios/memcpy.o
> -	$(E) "  CC       bios/e820.o"
> -	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/e820.c -o bios/e820.o
> -	$(E) "  CC       bios/int10.o"
> -	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/int10.c -o bios/int10.o
> -	$(E) "  CC       bios/int15.o"
> -	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/int15.c -o bios/int15.o
> -	$(E) "  CC       bios/entry.o"
> -	$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s bios/entry.S -o bios/entry.o
> +x86/bios.o: x86/bios/bios.bin x86/bios/bios-rom.h
> +
> +x86/bios/bios.bin.elf: x86/bios/entry.S x86/bios/e820.c x86/bios/int10.c x86/bios/int15.c x86/bios/rom.ld.S
> +	$(E) "  CC       x86/bios/memcpy.o"
> +	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/memcpy.c -o x86/bios/memcpy.o
> +	$(E) "  CC       x86/bios/e820.o"
> +	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/e820.c -o x86/bios/e820.o
> +	$(E) "  CC       x86/bios/int10.o"
> +	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/int10.c -o x86/bios/int10.o
> +	$(E) "  CC       x86/bios/int15.o"
> +	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/int15.c -o x86/bios/int15.o
> +	$(E) "  CC       x86/bios/entry.o"
> +	$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/entry.S -o x86/bios/entry.o
>  	$(E) "  LD      " $@
> -	$(Q) ld -T bios/rom.ld.S -o bios/bios.bin.elf bios/memcpy.o bios/entry.o bios/e820.o bios/int10.o bios/int15.o
> +	$(Q) ld -T x86/bios/rom.ld.S -o x86/bios/bios.bin.elf x86/bios/memcpy.o x86/bios/entry.o x86/bios/e820.o x86/bios/int10.o x86/bios/int15.o
>  
> -bios/bios.bin: bios/bios.bin.elf
> +x86/bios/bios.bin: x86/bios/bios.bin.elf
>  	$(E) "  OBJCOPY " $@
> -	$(Q) objcopy -O binary -j .text bios/bios.bin.elf bios/bios.bin
> +	$(Q) objcopy -O binary -j .text x86/bios/bios.bin.elf x86/bios/bios.bin
>  
> -bios/bios-rom.o: bios/bios-rom.S bios/bios.bin bios/bios-rom.h
> +x86/bios/bios-rom.o: x86/bios/bios-rom.S x86/bios/bios.bin x86/bios/bios-rom.h
>  	$(E) "  CC      " $@
> -	$(Q) $(CC) -c $(CFLAGS) bios/bios-rom.S -o bios/bios-rom.o
> +	$(Q) $(CC) -c $(CFLAGS) x86/bios/bios-rom.S -o x86/bios/bios-rom.o
>  
> -bios/bios-rom.h: bios/bios.bin.elf
> +x86/bios/bios-rom.h: x86/bios/bios.bin.elf
>  	$(E) "  NM      " $@
> -	$(Q) cd bios && sh gen-offsets.sh > bios-rom.h && cd ..
> +	$(Q) cd x86/bios && sh gen-offsets.sh > bios-rom.h && cd ..
>  
>  check: $(PROGRAM)
>  	$(MAKE) -C tests
> @@ -263,10 +287,10 @@ check: $(PROGRAM)
>  
>  clean:
>  	$(E) "  CLEAN"
> -	$(Q) rm -f bios/*.bin
> -	$(Q) rm -f bios/*.elf
> -	$(Q) rm -f bios/*.o
> -	$(Q) rm -f bios/bios-rom.h
> +	$(Q) rm -f x86/bios/*.bin
> +	$(Q) rm -f x86/bios/*.elf
> +	$(Q) rm -f x86/bios/*.o
> +	$(Q) rm -f x86/bios/bios-rom.h
>  	$(Q) rm -f tests/boot/boot_test.iso
>  	$(Q) rm -rf tests/boot/rootfs/
>  	$(Q) rm -f $(DEPS) $(OBJS) $(PROGRAM) $(GUEST_INIT)
> diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
> index 33de4f6..9148d83 100644
> --- a/tools/kvm/builtin-run.c
> +++ b/tools/kvm/builtin-run.c
> @@ -568,7 +568,7 @@ static const char *host_kernels[] = {
>  
>  static const char *default_kernels[] = {
>  	"./bzImage",
> -	"../../arch/x86/boot/bzImage",
> +	"../../arch/" BUILD_ARCH "/boot/bzImage",
>  	NULL
>  };
>  
> @@ -886,7 +886,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
>  
>  	kvm->vmlinux		= vmlinux_filename;
>  
> -	ioport__setup_legacy();
> +	ioport__setup_arch();
>  
>  	rtc__init();
>  
> @@ -931,7 +931,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
>  
>  	kvm__start_timer(kvm);
>  
> -	kvm__setup_bios(kvm);
> +	kvm__arch_setup_firmware(kvm);
>  
>  	for (i = 0; i < nrcpus; i++) {
>  		kvm_cpus[i] = kvm_cpu__init(kvm, i);
> diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
> index 5b857dd..61a70ec 100644
> --- a/tools/kvm/include/kvm/ioport.h
> +++ b/tools/kvm/include/kvm/ioport.h
> @@ -28,7 +28,7 @@ struct ioport_operations {
>  	bool (*io_out)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size);
>  };
>  
> -void ioport__setup_legacy(void);
> +void ioport__setup_arch(void);
>  
>  u16 ioport__register(u16 port, struct ioport_operations *ops, int count, void *param);
>  
> diff --git a/tools/kvm/include/kvm/kvm-cpu.h b/tools/kvm/include/kvm/kvm-cpu.h
> index 01540ac..719e286 100644
> --- a/tools/kvm/include/kvm/kvm-cpu.h
> +++ b/tools/kvm/include/kvm/kvm-cpu.h
> @@ -1,32 +1,7 @@
>  #ifndef KVM__KVM_CPU_H
>  #define KVM__KVM_CPU_H
>  
> -#include <linux/kvm.h>	/* for struct kvm_regs */
> -
> -#include <pthread.h>
> -
> -struct kvm;
> -
> -struct kvm_cpu {
> -	pthread_t		thread;		/* VCPU thread */
> -
> -	unsigned long		cpu_id;
> -
> -	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 */
> -
> -	u8			is_running;
> -	u8			paused;
> -
> -	struct kvm_coalesced_mmio_ring	*ring;
> -};
> +#include "kvm/kvm-cpu-arch.h"
>  
>  struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id);
>  void kvm_cpu__delete(struct kvm_cpu *vcpu);
> diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
> index 2b3024a..ca1acc0 100644
> --- a/tools/kvm/include/kvm/kvm.h
> +++ b/tools/kvm/include/kvm/kvm.h
> @@ -1,22 +1,13 @@
>  #ifndef KVM__KVM_H
>  #define KVM__KVM_H
>  
> -#include "kvm/interrupt.h"
> -#include "kvm/segment.h"
> +#include "kvm/kvm-arch.h"
>  
>  #include <stdbool.h>
>  #include <linux/types.h>
>  #include <time.h>
>  #include <signal.h>
>  
> -#define KVM_NR_CPUS		(255)
> -
> -/*
> - * The hole includes VESA framebuffer and PCI memory.
> - */
> -#define KVM_32BIT_GAP_SIZE	(768 << 20)
> -#define KVM_32BIT_GAP_START	((1ULL << 32) - KVM_32BIT_GAP_SIZE)
> -
>  #define SIGKVMEXIT		(SIGRTMIN + 0)
>  #define SIGKVMPAUSE		(SIGRTMIN + 1)
>  #define SIGKVMSTOP		(SIGRTMIN + 4)
> @@ -25,33 +16,15 @@
>  #define KVM_PID_FILE_PATH	"/.kvm-tools/"
>  #define HOME_DIR		getenv("HOME")
>  
> -struct kvm {
> -	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
> -	int			vm_fd;		/* For VM ioctls() */
> -	timer_t			timerid;	/* Posix timer for interrupts */
> -
> -	int			nrcpus;		/* Number of cpus to run */
> -
> -	u32			mem_slots;	/* for KVM_SET_USER_MEMORY_REGION */
> -
> -	u64			ram_size;
> -	void			*ram_start;
> -
> -	bool			nmi_disabled;
> -
> -	bool			single_step;
> +#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
>  
> -	u16			boot_selector;
> -	u16			boot_ip;
> -	u16			boot_sp;
> +#define DEFINE_KVM_EXT(ext)		\
> +	.name = #ext,			\
> +	.code = ext
>  
> -	struct interrupt_table	interrupt_table;
> -
> -	const char		*vmlinux;
> -	struct disk_image       **disks;
> -	int                     nr_disks;
> -
> -	const char		*name;
> +struct kvm_ext {
> +	const char *name;
> +	int code;
>  };
>  
>  void kvm__set_dir(const char *fmt, ...);
> @@ -64,7 +37,6 @@ void kvm__init_ram(struct kvm *kvm);
>  void kvm__delete(struct kvm *kvm);
>  bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
>  			const char *initrd_filename, const char *kernel_cmdline, u16 vidmode);
> -void kvm__setup_bios(struct kvm *kvm);
>  void kvm__start_timer(struct kvm *kvm);
>  void kvm__stop_timer(struct kvm *kvm);
>  void kvm__irq_line(struct kvm *kvm, int irq, int level);
> @@ -81,6 +53,13 @@ int kvm__get_sock_by_instance(const char *name);
>  int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
>  void kvm__remove_socket(const char *name);
>  
> +void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name);
> +void kvm__arch_setup_firmware(struct kvm *kvm);
> +bool kvm__arch_cpu_supports_vm(void);
> +
> +int load_flat_binary(struct kvm *kvm, int fd);
> +bool load_bzimage(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline, u16 vidmode);
> +
>  /*
>   * Debugging
>   */
> @@ -98,11 +77,4 @@ static inline void *guest_flat_to_host(struct kvm *kvm, unsigned long offset)
>  	return kvm->ram_start + offset;
>  }
>  
> -static inline void *guest_real_to_host(struct kvm *kvm, u16 selector, u16 offset)
> -{
> -	unsigned long flat = segment_to_flat(selector, offset);
> -
> -	return guest_flat_to_host(kvm, flat);
> -}
> -
>  #endif /* KVM__KVM_H */
> diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c
> index 7cbc44e..965cfc2 100644
> --- a/tools/kvm/ioport.c
> +++ b/tools/kvm/ioport.c
> @@ -52,34 +52,6 @@ static int ioport_insert(struct rb_root *root, struct ioport *data)
>  	return rb_int_insert(root, &data->node);
>  }
>  
> -static bool debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> -{
> -	exit(EXIT_SUCCESS);
> -}
> -
> -static struct ioport_operations debug_ops = {
> -	.io_out		= debug_io_out,
> -};
> -
> -static bool dummy_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> -{
> -	return true;
> -}
> -
> -static bool dummy_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> -{
> -	return true;
> -}
> -
> -static struct ioport_operations dummy_read_write_ioport_ops = {
> -	.io_in		= dummy_io_in,
> -	.io_out		= dummy_io_out,
> -};
> -
> -static struct ioport_operations dummy_write_only_ioport_ops = {
> -	.io_out		= dummy_io_out,
> -};
> -
>  u16 ioport__register(u16 port, struct ioport_operations *ops, int count, void *param)
>  {
>  	struct ioport *entry;
> @@ -164,29 +136,3 @@ error:
>  
>  	return !ioport_debug;
>  }
> -
> -void ioport__setup_legacy(void)
> -{
> -	/* 0x0020 - 0x003F - 8259A PIC 1 */
> -	ioport__register(0x0020, &dummy_read_write_ioport_ops, 2, NULL);
> -
> -	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
> -	ioport__register(0x0040, &dummy_read_write_ioport_ops, 4, NULL);
> -
> -	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
> -	ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
> -
> -	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
> -	   internal debugging purposes.  */
> -	ioport__register(IOPORT_DBG, &debug_ops, 1, NULL);
> -
> -	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
> -	ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
> -
> -	/* 0x00F0 - 0x00FF - Math co-processor */
> -	ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
> -
> -	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
> -	ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
> -	ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
> -}
> diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
> index 0ad6f3b..5aba3bb 100644
> --- a/tools/kvm/kvm-cpu.c
> +++ b/tools/kvm/kvm-cpu.c
> @@ -4,8 +4,6 @@
>  #include "kvm/util.h"
>  #include "kvm/kvm.h"
>  
> -#include <asm/msr-index.h>
> -
>  #include <sys/ioctl.h>
>  #include <sys/mman.h>
>  #include <signal.h>
> @@ -14,106 +12,9 @@
>  #include <errno.h>
>  #include <stdio.h>
>  
> -#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
> -
>  extern struct kvm_cpu *kvm_cpus[KVM_NR_CPUS];
>  extern __thread struct kvm_cpu *current_kvm_cpu;
>  
> -static int debug_fd;
> -
> -void kvm_cpu__set_debug_fd(int fd)
> -{
> -	debug_fd = fd;
> -}
> -
> -int kvm_cpu__get_debug_fd(void)
> -{
> -	return debug_fd;
> -}
> -
> -static inline bool is_in_protected_mode(struct kvm_cpu *vcpu)
> -{
> -	return vcpu->sregs.cr0 & 0x01;
> -}
> -
> -static inline u64 ip_to_flat(struct kvm_cpu *vcpu, u64 ip)
> -{
> -	u64 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(vcpu))
> -		return ip;
> -
> -	cs = vcpu->sregs.cs.selector;
> -
> -	return ip + (cs << 4);
> -}
> -
> -static inline u32 selector_to_base(u16 selector)
> -{
> -	/*
> -	 * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
> -	 */
> -	return (u32)selector * 16;
> -}
> -
> -static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
> -{
> -	struct kvm_cpu *vcpu;
> -
> -	vcpu		= calloc(1, sizeof *vcpu);
> -	if (!vcpu)
> -		return NULL;
> -
> -	vcpu->kvm	= kvm;
> -
> -	return vcpu;
> -}
> -
> -void kvm_cpu__delete(struct kvm_cpu *vcpu)
> -{
> -	if (vcpu->msrs)
> -		free(vcpu->msrs);
> -
> -	free(vcpu);
> -}
> -
> -struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id)
> -{
> -	struct kvm_cpu *vcpu;
> -	int mmap_size;
> -	int coalesced_offset;
> -
> -	vcpu		= kvm_cpu__new(kvm);
> -	if (!vcpu)
> -		return NULL;
> -
> -	vcpu->cpu_id	= cpu_id;
> -
> -	vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
> -	if (vcpu->vcpu_fd < 0)
> -		die_perror("KVM_CREATE_VCPU ioctl");
> -
> -	mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
> -	if (mmap_size < 0)
> -		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
> -
> -	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
> -	if (vcpu->kvm_run == MAP_FAILED)
> -		die("unable to mmap vcpu fd");
> -
> -	coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
> -	if (coalesced_offset)
> -		vcpu->ring = (void *)vcpu->kvm_run + (coalesced_offset * PAGE_SIZE);
> -
> -	vcpu->is_running = true;
> -
> -	return vcpu;
> -}
> -
>  void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
>  {
>  	struct kvm_guest_debug debug = {
> @@ -124,278 +25,6 @@ void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
>  		pr_warning("KVM_SET_GUEST_DEBUG failed");
>  }
>  
> -static struct kvm_msrs *kvm_msrs__new(size_t nmsrs)
> -{
> -	struct kvm_msrs *vcpu = calloc(1, sizeof(*vcpu) + (sizeof(struct kvm_msr_entry) * nmsrs));
> -
> -	if (!vcpu)
> -		die("out of memory");
> -
> -	return vcpu;
> -}
> -
> -#define KVM_MSR_ENTRY(_index, _data)	\
> -	(struct kvm_msr_entry) { .index = _index, .data = _data }
> -
> -static void kvm_cpu__setup_msrs(struct kvm_cpu *vcpu)
> -{
> -	unsigned long ndx = 0;
> -
> -	vcpu->msrs = kvm_msrs__new(100);
> -
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_CS,	0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_ESP,	0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_EIP,	0x0);
> -#ifdef CONFIG_X86_64
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_STAR,			0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_CSTAR,			0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_KERNEL_GS_BASE,		0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_SYSCALL_MASK,		0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_LSTAR,			0x0);
> -#endif
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_TSC,		0x0);
> -	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_MISC_ENABLE,
> -						MSR_IA32_MISC_ENABLE_FAST_STRING);
> -
> -	vcpu->msrs->nmsrs	= ndx;
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_SET_MSRS, vcpu->msrs) < 0)
> -		die_perror("KVM_SET_MSRS failed");
> -}
> -
> -static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
> -{
> -	vcpu->fpu = (struct kvm_fpu) {
> -		.fcw		= 0x37f,
> -		.mxcsr		= 0x1f80,
> -	};
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_SET_FPU, &vcpu->fpu) < 0)
> -		die_perror("KVM_SET_FPU failed");
> -}
> -
> -static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
> -{
> -	vcpu->regs = (struct kvm_regs) {
> -		/* We start the guest in 16-bit real mode  */
> -		.rflags		= 0x0000000000000002ULL,
> -
> -		.rip		= vcpu->kvm->boot_ip,
> -		.rsp		= vcpu->kvm->boot_sp,
> -		.rbp		= vcpu->kvm->boot_sp,
> -	};
> -
> -	if (vcpu->regs.rip > USHRT_MAX)
> -		die("ip 0x%llx is too high for real mode", (u64) vcpu->regs.rip);
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
> -		die_perror("KVM_SET_REGS failed");
> -}
> -
> -static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
> -{
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> -		die_perror("KVM_GET_SREGS failed");
> -
> -	vcpu->sregs.cs.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.cs.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.ss.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.ss.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.ds.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.ds.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.es.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.es.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.fs.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.fs.base	= selector_to_base(vcpu->kvm->boot_selector);
> -	vcpu->sregs.gs.selector	= vcpu->kvm->boot_selector;
> -	vcpu->sregs.gs.base	= selector_to_base(vcpu->kvm->boot_selector);
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_SET_SREGS, &vcpu->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 *vcpu)
> -{
> -	kvm_cpu__setup_sregs(vcpu);
> -	kvm_cpu__setup_regs(vcpu);
> -	kvm_cpu__setup_fpu(vcpu);
> -	kvm_cpu__setup_msrs(vcpu);
> -}
> -
> -static void print_dtable(const char *name, struct kvm_dtable *dtable)
> -{
> -	dprintf(debug_fd, " %s                 %016llx  %08hx\n",
> -		name, (u64) dtable->base, (u16) dtable->limit);
> -}
> -
> -static void print_segment(const char *name, struct kvm_segment *seg)
> -{
> -	dprintf(debug_fd, " %s       %04hx      %016llx  %08x  %02hhx    %x %x   %x  %x %x %x %x\n",
> -		name, (u16) seg->selector, (u64) seg->base, (u32) seg->limit,
> -		(u8) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
> -}
> -
> -void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
> -{
> -	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(vcpu->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;
> -
> -	dprintf(debug_fd, "\n Registers:\n");
> -	dprintf(debug_fd,   " ----------\n");
> -	dprintf(debug_fd, " rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
> -	dprintf(debug_fd, " rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
> -	dprintf(debug_fd, " rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
> -	dprintf(debug_fd, " rbp: %016lx    r8: %016lx    r9: %016lx\n", rbp, r8,  r9);
> -	dprintf(debug_fd, " r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
> -	dprintf(debug_fd, " r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
> -
> -	if (ioctl(vcpu->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;
> -
> -	dprintf(debug_fd, " cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
> -	dprintf(debug_fd, " cr4: %016lx   cr8: %016lx\n", cr4, cr8);
> -	dprintf(debug_fd, "\n Segment registers:\n");
> -	dprintf(debug_fd,   " ------------------\n");
> -	dprintf(debug_fd, " 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);
> -
> -	dprintf(debug_fd, "\n APIC:\n");
> -	dprintf(debug_fd,   " -----\n");
> -	dprintf(debug_fd, " efer: %016llx  apic base: %016llx  nmi: %s\n",
> -		(u64) sregs.efer, (u64) sregs.apic_base,
> -		(vcpu->kvm->nmi_disabled ? "disabled" : "enabled"));
> -
> -	dprintf(debug_fd, "\n Interrupt bitmap:\n");
> -	dprintf(debug_fd,   " -----------------\n");
> -	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
> -		dprintf(debug_fd, " %016llx", (u64) sregs.interrupt_bitmap[i]);
> -	dprintf(debug_fd, "\n");
> -}
> -
> -#define MAX_SYM_LEN		128
> -
> -void kvm_cpu__show_code(struct kvm_cpu *vcpu)
> -{
> -	unsigned int code_bytes = 64;
> -	unsigned int code_prologue = code_bytes * 43 / 64;
> -	unsigned int code_len = code_bytes;
> -	char sym[MAX_SYM_LEN];
> -	unsigned char c;
> -	unsigned int i;
> -	u8 *ip;
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
> -		die("KVM_GET_REGS failed");
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> -		die("KVM_GET_SREGS failed");
> -
> -	ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip) - code_prologue);
> -
> -	dprintf(debug_fd, "\n Code:\n");
> -	dprintf(debug_fd,   " -----\n");
> -
> -	symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
> -
> -	dprintf(debug_fd, " rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
> -
> -	for (i = 0; i < code_len; i++, ip++) {
> -		if (!host_ptr_in_ram(vcpu->kvm, ip))
> -			break;
> -
> -		c = *ip;
> -
> -		if (ip == guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip)))
> -			dprintf(debug_fd, " <%02x>", c);
> -		else
> -			dprintf(debug_fd, " %02x", c);
> -	}
> -
> -	dprintf(debug_fd, "\n");
> -
> -	dprintf(debug_fd, "\n Stack:\n");
> -	dprintf(debug_fd,   " ------\n");
> -	kvm__dump_mem(vcpu->kvm, vcpu->regs.rsp, 32);
> -}
> -
> -void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
> -{
> -	u64 *pte1;
> -	u64 *pte2;
> -	u64 *pte3;
> -	u64 *pte4;
> -
> -	if (!is_in_protected_mode(vcpu))
> -		return;
> -
> -	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> -		die("KVM_GET_SREGS failed");
> -
> -	pte4	= guest_flat_to_host(vcpu->kvm, vcpu->sregs.cr3);
> -	if (!host_ptr_in_ram(vcpu->kvm, pte4))
> -		return;
> -
> -	pte3	= guest_flat_to_host(vcpu->kvm, (*pte4 & ~0xfff));
> -	if (!host_ptr_in_ram(vcpu->kvm, pte3))
> -		return;
> -
> -	pte2	= guest_flat_to_host(vcpu->kvm, (*pte3 & ~0xfff));
> -	if (!host_ptr_in_ram(vcpu->kvm, pte2))
> -		return;
> -
> -	pte1	= guest_flat_to_host(vcpu->kvm, (*pte2 & ~0xfff));
> -	if (!host_ptr_in_ram(vcpu->kvm, pte1))
> -		return;
> -
> -	dprintf(debug_fd, "Page Tables:\n");
> -	if (*pte2 & (1 << 7))
> -		dprintf(debug_fd, " pte4: %016llx   pte3: %016llx"
> -			"   pte2: %016llx\n",
> -			*pte4, *pte3, *pte2);
> -	else
> -		dprintf(debug_fd, " pte4: %016llx  pte3: %016llx   pte2: %016"
> -			"llx   pte1: %016llx\n",
> -			*pte4, *pte3, *pte2, *pte1);
> -}
> -
>  void kvm_cpu__run(struct kvm_cpu *vcpu)
>  {
>  	int err;
> @@ -454,7 +83,6 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
>  	signal(SIGKVMEXIT, kvm_cpu_signal_handler);
>  	signal(SIGKVMPAUSE, kvm_cpu_signal_handler);
>  
> -	kvm_cpu__setup_cpuid(cpu);
>  	kvm_cpu__reset_vcpu(cpu);
>  
>  	if (cpu->kvm->single_step)
> diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
> index 252bd18..7ce1640 100644
> --- a/tools/kvm/kvm.c
> +++ b/tools/kvm/kvm.c
> @@ -1,10 +1,5 @@
>  #include "kvm/kvm.h"
> -
> -#include "kvm/boot-protocol.h"
> -#include "kvm/cpufeature.h"
>  #include "kvm/read-write.h"
> -#include "kvm/interrupt.h"
> -#include "kvm/mptable.h"
>  #include "kvm/util.h"
>  #include "kvm/mutex.h"
>  #include "kvm/kvm-cpu.h"
> @@ -12,14 +7,11 @@
>  
>  #include <linux/kvm.h>
>  
> -#include <asm/bootparam.h>
> -
>  #include <sys/un.h>
>  #include <sys/types.h>
>  #include <sys/socket.h>
>  #include <sys/ioctl.h>
>  #include <sys/mman.h>
> -#include <sys/stat.h>
>  #include <stdbool.h>
>  #include <assert.h>
>  #include <limits.h>
> @@ -58,29 +50,11 @@ const char *kvm_exit_reasons[] = {
>  	DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTERNAL_ERROR),
>  };
>  
> -#define DEFINE_KVM_EXT(ext)		\
> -	.name = #ext,			\
> -	.code = ext
> -
> -struct {
> -	const char *name;
> -	int code;
> -} kvm_req_ext[] = {
> -	{ DEFINE_KVM_EXT(KVM_CAP_COALESCED_MMIO) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_SET_TSS_ADDR) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_PIT2) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_USER_MEMORY) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_ROUTING) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_HLT) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_INJECT_STATUS) },
> -	{ DEFINE_KVM_EXT(KVM_CAP_EXT_CPUID) },
> -};
> -
>  extern struct kvm *kvm;
>  extern struct kvm_cpu *kvm_cpus[KVM_NR_CPUS];
>  static int pause_event;
>  static DEFINE_MUTEX(pause_lock);
> +extern struct kvm_ext kvm_req_ext[];
>  
>  static char kvm_dir[PATH_MAX];
>  
> @@ -127,7 +101,9 @@ static int kvm__check_extensions(struct kvm *kvm)
>  {
>  	unsigned int i;
>  
> -	for (i = 0; i < ARRAY_SIZE(kvm_req_ext); i++) {
> +	for (i = 0; ; i++) {
> +		if (!kvm_req_ext[i].name)
> +			break;
>  		if (!kvm__supports_extension(kvm, kvm_req_ext[i].code)) {
>  			pr_error("Unsuppored KVM extension detected: %s",
>  				kvm_req_ext[i].name);
> @@ -261,48 +237,6 @@ void kvm__delete(struct kvm *kvm)
>  	free(kvm);
>  }
>  
> -static bool kvm__cpu_supports_vm(void)
> -{
> -	struct cpuid_regs regs;
> -	u32 eax_base;
> -	int feature;
> -
> -	regs	= (struct cpuid_regs) {
> -		.eax		= 0x00,
> -	};
> -	host_cpuid(&regs);
> -
> -	switch (regs.ebx) {
> -	case CPUID_VENDOR_INTEL_1:
> -		eax_base	= 0x00;
> -		feature		= KVM__X86_FEATURE_VMX;
> -		break;
> -
> -	case CPUID_VENDOR_AMD_1:
> -		eax_base	= 0x80000000;
> -		feature		= KVM__X86_FEATURE_SVM;
> -		break;
> -
> -	default:
> -		return false;
> -	}
> -
> -	regs	= (struct cpuid_regs) {
> -		.eax		= eax_base,
> -	};
> -	host_cpuid(&regs);
> -
> -	if (regs.eax < eax_base + 0x01)
> -		return false;
> -
> -	regs	= (struct cpuid_regs) {
> -		.eax		= eax_base + 0x01
> -	};
> -	host_cpuid(&regs);
> -
> -	return regs.ecx & (1 << feature);
> -}
> -
>  /*
>   * Note: KVM_SET_USER_MEMORY_REGION assumes that we don't pass overlapping
>   * memory regions to it. Therefore, be careful if you use this function for
> @@ -325,47 +259,6 @@ void kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspac
>  		die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
>  }
>  
> -/*
> - * Allocating RAM size bigger than 4GB requires us to leave a gap
> - * in the RAM which is used for PCI MMIO, hotplug, and unconfigured
> - * devices (see documentation of e820_setup_gap() for details).
> - *
> - * If we're required to initialize RAM bigger than 4GB, we will create
> - * a gap between 0xe0000000 and 0x100000000 in the guest virtual mem space.
> - */
> -
> -void kvm__init_ram(struct kvm *kvm)
> -{
> -	u64	phys_start, phys_size;
> -	void	*host_mem;
> -
> -	if (kvm->ram_size < KVM_32BIT_GAP_START) {
> -		/* Use a single block of RAM for 32bit RAM */
> -
> -		phys_start = 0;
> -		phys_size  = kvm->ram_size;
> -		host_mem   = kvm->ram_start;
> -
> -		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> -	} else {
> -		/* First RAM range from zero to the PCI gap: */
> -
> -		phys_start = 0;
> -		phys_size  = KVM_32BIT_GAP_START;
> -		host_mem   = kvm->ram_start;
> -
> -		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> -
> -		/* Second RAM range from 4GB to the end of RAM: */
> -
> -		phys_start = 0x100000000ULL;
> -		phys_size  = kvm->ram_size - phys_size;
> -		host_mem   = kvm->ram_start + phys_start;
> -
> -		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> -	}
> -}
> -
>  int kvm__recommended_cpus(struct kvm *kvm)
>  {
>  	int ret;
> @@ -410,11 +303,10 @@ int kvm__max_cpus(struct kvm *kvm)
>  
>  struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
>  {
> -	struct kvm_pit_config pit_config = { .flags = 0, };
>  	struct kvm *kvm;
>  	int ret;
>  
> -	if (!kvm__cpu_supports_vm())
> +	if (!kvm__arch_cpu_supports_vm())
>  		die("Your CPU does not support hardware virtualization");
>  
>  	kvm = kvm__new();
> @@ -442,36 +334,7 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
>  	if (kvm__check_extensions(kvm))
>  		die("A required KVM extention is not supported by OS");
>  
> -	ret = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
> -	if (ret < 0)
> -		die_perror("KVM_SET_TSS_ADDR ioctl");
> -
> -	ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config);
> -	if (ret < 0)
> -		die_perror("KVM_CREATE_PIT2 ioctl");
> -
> -	kvm->ram_size		= ram_size;
> -
> -	if (kvm->ram_size < KVM_32BIT_GAP_START) {
> -		kvm->ram_start = mmap(NULL, ram_size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
> -	} else {
> -		kvm->ram_start = mmap(NULL, ram_size + KVM_32BIT_GAP_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
> -		if (kvm->ram_start != MAP_FAILED) {
> -			/*
> -			 * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
> -			 * if we accidently write to it, we will know.
> -			 */
> -			mprotect(kvm->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
> -		}
> -	}
> -	if (kvm->ram_start == MAP_FAILED)
> -		die("out of memory");
> -
> -	madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
> -
> -	ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
> -	if (ret < 0)
> -		die_perror("KVM_CREATE_IRQCHIP ioctl");
> +	kvm__arch_init(kvm, kvm_dev, ram_size, name);
>  
>  	kvm->name = name;
>  
> @@ -480,141 +343,6 @@ struct kvm *kvm__init(const char *kvm_dev, u64 ram_size, const char *name)
>  	return kvm;
>  }
>  
> -#define BOOT_LOADER_SELECTOR	0x1000
> -#define BOOT_LOADER_IP		0x0000
> -#define BOOT_LOADER_SP		0x8000
> -#define BOOT_CMDLINE_OFFSET	0x20000
> -
> -#define BOOT_PROTOCOL_REQUIRED	0x206
> -#define LOAD_HIGH		0x01
> -
> -static int load_flat_binary(struct kvm *kvm, int fd)
> -{
> -	void *p;
> -	int nr;
> -
> -	if (lseek(fd, 0, SEEK_SET) < 0)
> -		die_perror("lseek");
> -
> -	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
> -
> -	while ((nr = read(fd, p, 65536)) > 0)
> -		p += nr;
> -
> -	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
> -	kvm->boot_ip		= BOOT_LOADER_IP;
> -	kvm->boot_sp		= BOOT_LOADER_SP;
> -
> -	return true;
> -}
> -
> -static const char *BZIMAGE_MAGIC	= "HdrS";
> -
> -static bool load_bzimage(struct kvm *kvm, int fd_kernel,
> -			int fd_initrd, const char *kernel_cmdline, u16 vidmode)
> -{
> -	struct boot_params *kern_boot;
> -	unsigned long setup_sects;
> -	struct boot_params boot;
> -	size_t cmdline_size;
> -	ssize_t setup_size;
> -	void *p;
> -	int nr;
> -
> -	/*
> -	 * See Documentation/x86/boot.txt for details no bzImage on-disk and
> -	 * memory layout.
> -	 */
> -
> -	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> -		die_perror("lseek");
> -
> -	if (read(fd_kernel, &boot, sizeof(boot)) != sizeof(boot))
> -		return false;
> -
> -	if (memcmp(&boot.hdr.header, BZIMAGE_MAGIC, strlen(BZIMAGE_MAGIC)))
> -		return false;
> -
> -	if (boot.hdr.version < BOOT_PROTOCOL_REQUIRED)
> -		die("Too old kernel");
> -
> -	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> -		die_perror("lseek");
> -
> -	if (!boot.hdr.setup_sects)
> -		boot.hdr.setup_sects = BZ_DEFAULT_SETUP_SECTS;
> -	setup_sects = boot.hdr.setup_sects + 1;
> -
> -	setup_size = setup_sects << 9;
> -	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
> -
> -	/* copy setup.bin to mem*/
> -	if (read(fd_kernel, p, setup_size) != setup_size)
> -		die_perror("read");
> -
> -	/* copy vmlinux.bin to BZ_KERNEL_START*/
> -	p = guest_flat_to_host(kvm, BZ_KERNEL_START);
> -
> -	while ((nr = read(fd_kernel, p, 65536)) > 0)
> -		p += nr;
> -
> -	p = guest_flat_to_host(kvm, BOOT_CMDLINE_OFFSET);
> -	if (kernel_cmdline) {
> -		cmdline_size = strlen(kernel_cmdline) + 1;
> -		if (cmdline_size > boot.hdr.cmdline_size)
> -			cmdline_size = boot.hdr.cmdline_size;
> -
> -		memset(p, 0, boot.hdr.cmdline_size);
> -		memcpy(p, kernel_cmdline, cmdline_size - 1);
> -	}
> -
> -	kern_boot	= guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, 0x00);
> -
> -	kern_boot->hdr.cmd_line_ptr	= BOOT_CMDLINE_OFFSET;
> -	kern_boot->hdr.type_of_loader	= 0xff;
> -	kern_boot->hdr.heap_end_ptr	= 0xfe00;
> -	kern_boot->hdr.loadflags	|= CAN_USE_HEAP;
> -	kern_boot->hdr.vid_mode		= vidmode;
> -
> -	/*
> -	 * Read initrd image into guest memory
> -	 */
> -	if (fd_initrd >= 0) {
> -		struct stat initrd_stat;
> -		unsigned long addr;
> -
> -		if (fstat(fd_initrd, &initrd_stat))
> -			die_perror("fstat");
> -
> -		addr = boot.hdr.initrd_addr_max & ~0xfffff;
> -		for (;;) {
> -			if (addr < BZ_KERNEL_START)
> -				die("Not enough memory for initrd");
> -			else if (addr < (kvm->ram_size - initrd_stat.st_size))
> -				break;
> -			addr -= 0x100000;
> -		}
> -
> -		p = guest_flat_to_host(kvm, addr);
> -		nr = read(fd_initrd, p, initrd_stat.st_size);
> -		if (nr != initrd_stat.st_size)
> -			die("Failed to read initrd");
> -
> -		kern_boot->hdr.ramdisk_image	= addr;
> -		kern_boot->hdr.ramdisk_size	= initrd_stat.st_size;
> -	}
> -
> -	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
> -	/*
> -	 * The real-mode setup code starts at offset 0x200 of a bzImage. See
> -	 * Documentation/x86/boot.txt for details.
> -	 */
> -	kvm->boot_ip		= BOOT_LOADER_IP + 0x200;
> -	kvm->boot_sp		= BOOT_LOADER_SP;
> -
> -	return true;
> -}
> -
>  /* RFC 1952 */
>  #define GZIP_ID1		0x1f
>  #define GZIP_ID2		0x8b
> @@ -675,24 +403,6 @@ found_kernel:
>  	return ret;
>  }
>  
> -/**
> - * kvm__setup_bios - inject BIOS into guest system memory
> - * @kvm - guest system descriptor
> - *
> - * This function is a main routine where we poke guest memory
> - * and install BIOS there.
> - */
> -void kvm__setup_bios(struct kvm *kvm)
> -{
> -	/* standart minimal configuration */
> -	setup_bios(kvm);
> -
> -	/* FIXME: SMP, ACPI and friends here */
> -
> -	/* MP table */
> -	mptable_setup(kvm, kvm->nrcpus);
> -}
> -
>  #define TIMER_INTERVAL_NS 1000000	/* 1 msec */
>  
>  /*
> @@ -732,27 +442,6 @@ void kvm__stop_timer(struct kvm *kvm)
>  	kvm->timerid = 0;
>  }
>  
> -void kvm__irq_line(struct kvm *kvm, int irq, int level)
> -{
> -	struct kvm_irq_level irq_level;
> -
> -	irq_level	= (struct kvm_irq_level) {
> -		{
> -			.irq		= irq,
> -		},
> -		.level		= level,
> -	};
> -
> -	if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
> -		die_perror("KVM_IRQ_LINE failed");
> -}
> -
> -void kvm__irq_trigger(struct kvm *kvm, int irq)
> -{
> -	kvm__irq_line(kvm, irq, 1);
> -	kvm__irq_line(kvm, irq, 0);
> -}
> -
>  void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size)
>  {
>  	unsigned char *p;
> diff --git a/tools/kvm/bios.c b/tools/kvm/x86/bios.c
> similarity index 100%
> rename from tools/kvm/bios.c
> rename to tools/kvm/x86/bios.c
> diff --git a/tools/kvm/bios/.gitignore b/tools/kvm/x86/bios/.gitignore
> similarity index 100%
> rename from tools/kvm/bios/.gitignore
> rename to tools/kvm/x86/bios/.gitignore
> diff --git a/tools/kvm/bios/bios-rom.S b/tools/kvm/x86/bios/bios-rom.S
> similarity index 80%
> rename from tools/kvm/bios/bios-rom.S
> rename to tools/kvm/x86/bios/bios-rom.S
> index dc52b1e..3269ce9 100644
> --- a/tools/kvm/bios/bios-rom.S
> +++ b/tools/kvm/x86/bios/bios-rom.S
> @@ -8,5 +8,5 @@
>  #endif
>  
>  GLOBAL(bios_rom)
> -	.incbin "bios/bios.bin"
> +	.incbin "x86/bios/bios.bin"
>  END(bios_rom)
> diff --git a/tools/kvm/bios/e820.c b/tools/kvm/x86/bios/e820.c
> similarity index 100%
> rename from tools/kvm/bios/e820.c
> rename to tools/kvm/x86/bios/e820.c
> diff --git a/tools/kvm/bios/entry.S b/tools/kvm/x86/bios/entry.S
> similarity index 100%
> rename from tools/kvm/bios/entry.S
> rename to tools/kvm/x86/bios/entry.S
> diff --git a/tools/kvm/bios/gen-offsets.sh b/tools/kvm/x86/bios/gen-offsets.sh
> similarity index 100%
> rename from tools/kvm/bios/gen-offsets.sh
> rename to tools/kvm/x86/bios/gen-offsets.sh
> diff --git a/tools/kvm/bios/int10.c b/tools/kvm/x86/bios/int10.c
> similarity index 100%
> rename from tools/kvm/bios/int10.c
> rename to tools/kvm/x86/bios/int10.c
> diff --git a/tools/kvm/bios/int15.c b/tools/kvm/x86/bios/int15.c
> similarity index 100%
> rename from tools/kvm/bios/int15.c
> rename to tools/kvm/x86/bios/int15.c
> diff --git a/tools/kvm/bios/local.S b/tools/kvm/x86/bios/local.S
> similarity index 100%
> rename from tools/kvm/bios/local.S
> rename to tools/kvm/x86/bios/local.S
> diff --git a/tools/kvm/bios/macro.S b/tools/kvm/x86/bios/macro.S
> similarity index 100%
> rename from tools/kvm/bios/macro.S
> rename to tools/kvm/x86/bios/macro.S
> diff --git a/tools/kvm/bios/memcpy.c b/tools/kvm/x86/bios/memcpy.c
> similarity index 100%
> rename from tools/kvm/bios/memcpy.c
> rename to tools/kvm/x86/bios/memcpy.c
> diff --git a/tools/kvm/bios/rom.ld.S b/tools/kvm/x86/bios/rom.ld.S
> similarity index 100%
> rename from tools/kvm/bios/rom.ld.S
> rename to tools/kvm/x86/bios/rom.ld.S
> diff --git a/tools/kvm/cpuid.c b/tools/kvm/x86/cpuid.c
> similarity index 100%
> rename from tools/kvm/cpuid.c
> rename to tools/kvm/x86/cpuid.c
> diff --git a/tools/kvm/include/kvm/assembly.h b/tools/kvm/x86/include/kvm/assembly.h
> similarity index 100%
> rename from tools/kvm/include/kvm/assembly.h
> rename to tools/kvm/x86/include/kvm/assembly.h
> diff --git a/tools/kvm/include/kvm/barrier.h b/tools/kvm/x86/include/kvm/barrier.h
> similarity index 100%
> rename from tools/kvm/include/kvm/barrier.h
> rename to tools/kvm/x86/include/kvm/barrier.h
> diff --git a/tools/kvm/include/kvm/bios-export.h b/tools/kvm/x86/include/kvm/bios-export.h
> similarity index 100%
> rename from tools/kvm/include/kvm/bios-export.h
> rename to tools/kvm/x86/include/kvm/bios-export.h
> diff --git a/tools/kvm/include/kvm/bios.h b/tools/kvm/x86/include/kvm/bios.h
> similarity index 100%
> rename from tools/kvm/include/kvm/bios.h
> rename to tools/kvm/x86/include/kvm/bios.h
> diff --git a/tools/kvm/include/kvm/boot-protocol.h b/tools/kvm/x86/include/kvm/boot-protocol.h
> similarity index 100%
> rename from tools/kvm/include/kvm/boot-protocol.h
> rename to tools/kvm/x86/include/kvm/boot-protocol.h
> diff --git a/tools/kvm/include/kvm/cpufeature.h b/tools/kvm/x86/include/kvm/cpufeature.h
> similarity index 100%
> rename from tools/kvm/include/kvm/cpufeature.h
> rename to tools/kvm/x86/include/kvm/cpufeature.h
> diff --git a/tools/kvm/include/kvm/interrupt.h b/tools/kvm/x86/include/kvm/interrupt.h
> similarity index 100%
> rename from tools/kvm/include/kvm/interrupt.h
> rename to tools/kvm/x86/include/kvm/interrupt.h
> diff --git a/tools/kvm/x86/include/kvm/kvm-arch.h b/tools/kvm/x86/include/kvm/kvm-arch.h
> new file mode 100644
> index 0000000..02aa8b9
> --- /dev/null
> +++ b/tools/kvm/x86/include/kvm/kvm-arch.h
> @@ -0,0 +1,59 @@
> +#ifndef KVM__KVM_ARCH_H
> +#define KVM__KVM_ARCH_H
> +
> +#include "kvm/interrupt.h"
> +#include "kvm/segment.h"
> +
> +#include <stdbool.h>
> +#include <linux/types.h>
> +#include <time.h>
> +
> +#define KVM_NR_CPUS		(255)
> +
> +/*
> + * The hole includes VESA framebuffer and PCI memory.
> + */
> +#define KVM_32BIT_GAP_SIZE	(768 << 20)
> +#define KVM_32BIT_GAP_START	((1ULL << 32) - KVM_32BIT_GAP_SIZE)
> +
> +#define KVM_MMIO_START		KVM_32BIT_GAP_START
> +
> +struct kvm {
> +	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
> +	int			vm_fd;		/* For VM ioctls() */
> +	timer_t			timerid;	/* Posix timer for interrupts */
> +
> +	int			nrcpus;		/* Number of cpus to run */
> +
> +	u32			mem_slots;	/* for KVM_SET_USER_MEMORY_REGION */
> +
> +	u64			ram_size;
> +	void			*ram_start;
> +
> +	bool			nmi_disabled;
> +
> +	bool			single_step;
> +
> +	u16			boot_selector;
> +	u16			boot_ip;
> +	u16			boot_sp;
> +
> +	struct interrupt_table	interrupt_table;
> +
> +	const char		*vmlinux;
> +	struct disk_image       **disks;
> +	int                     nr_disks;
> +
> +	const char		*name;
> +};
> +
> +static inline void *guest_flat_to_host(struct kvm *kvm, unsigned long offset); /* In kvm.h */
> +
> +static inline void *guest_real_to_host(struct kvm *kvm, u16 selector, u16 offset)
> +{
> +	unsigned long flat = segment_to_flat(selector, offset);
> +
> +	return guest_flat_to_host(kvm, flat);
> +}
> +
> +#endif /* KVM__KVM_ARCH_H */
> diff --git a/tools/kvm/x86/include/kvm/kvm-cpu-arch.h b/tools/kvm/x86/include/kvm/kvm-cpu-arch.h
> new file mode 100644
> index 0000000..ed1c727
> --- /dev/null
> +++ b/tools/kvm/x86/include/kvm/kvm-cpu-arch.h
> @@ -0,0 +1,33 @@
> +#ifndef KVM__KVM_CPU_ARCH_H
> +#define KVM__KVM_CPU_ARCH_H
> +
> +/* Architecture-specific kvm_cpu definitions. */
> +
> +#include <linux/kvm.h>	/* for struct kvm_regs */
> +
> +#include <pthread.h>
> +
> +struct kvm;
> +
> +struct kvm_cpu {
> +	pthread_t		thread;		/* VCPU thread */
> +
> +	unsigned long		cpu_id;
> +
> +	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 */
> +
> +	u8			is_running;
> +	u8			paused;
> +
> +	struct kvm_coalesced_mmio_ring	*ring;
> +};
> +
> +#endif /* KVM__KVM_CPU_ARCH_H */
> diff --git a/tools/kvm/include/kvm/mptable.h b/tools/kvm/x86/include/kvm/mptable.h
> similarity index 100%
> rename from tools/kvm/include/kvm/mptable.h
> rename to tools/kvm/x86/include/kvm/mptable.h
> diff --git a/tools/kvm/interrupt.c b/tools/kvm/x86/interrupt.c
> similarity index 100%
> rename from tools/kvm/interrupt.c
> rename to tools/kvm/x86/interrupt.c
> diff --git a/tools/kvm/x86/ioport.c b/tools/kvm/x86/ioport.c
> new file mode 100644
> index 0000000..8a91bf2
> --- /dev/null
> +++ b/tools/kvm/x86/ioport.c
> @@ -0,0 +1,59 @@
> +#include "kvm/ioport.h"
> +
> +#include <stdlib.h>
> +
> +static bool debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> +{
> +	exit(EXIT_SUCCESS);
> +}
> +
> +static struct ioport_operations debug_ops = {
> +	.io_out		= debug_io_out,
> +};
> +
> +static bool dummy_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> +{
> +	return true;
> +}
> +
> +static bool dummy_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
> +{
> +	return true;
> +}
> +
> +static struct ioport_operations dummy_read_write_ioport_ops = {
> +	.io_in		= dummy_io_in,
> +	.io_out		= dummy_io_out,
> +};
> +
> +static struct ioport_operations dummy_write_only_ioport_ops = {
> +	.io_out		= dummy_io_out,
> +};
> +
> +void ioport__setup_arch(void)
> +{
> +	/* Legacy ioport setup */
> +
> +	/* 0x0020 - 0x003F - 8259A PIC 1 */
> +	ioport__register(0x0020, &dummy_read_write_ioport_ops, 2, NULL);
> +
> +	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
> +	ioport__register(0x0040, &dummy_read_write_ioport_ops, 4, NULL);
> +
> +	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
> +	ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
> +
> +	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
> +	   internal debugging purposes.  */
> +	ioport__register(IOPORT_DBG, &debug_ops, 1, NULL);
> +
> +	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
> +	ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
> +
> +	/* 0x00F0 - 0x00FF - Math co-processor */
> +	ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
> +
> +	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
> +	ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
> +	ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
> +}
> diff --git a/tools/kvm/irq.c b/tools/kvm/x86/irq.c
> similarity index 100%
> rename from tools/kvm/irq.c
> rename to tools/kvm/x86/irq.c
> diff --git a/tools/kvm/x86/kvm-cpu.c b/tools/kvm/x86/kvm-cpu.c
> new file mode 100644
> index 0000000..b26b208
> --- /dev/null
> +++ b/tools/kvm/x86/kvm-cpu.c
> @@ -0,0 +1,383 @@
> +#include "kvm/kvm-cpu.h"
> +
> +#include "kvm/symbol.h"
> +#include "kvm/util.h"
> +#include "kvm/kvm.h"
> +
> +#include <asm/msr-index.h>
> +
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <signal.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <stdio.h>
> +
> +static int debug_fd;
> +
> +void kvm_cpu__set_debug_fd(int fd)
> +{
> +	debug_fd = fd;
> +}
> +
> +int kvm_cpu__get_debug_fd(void)
> +{
> +	return debug_fd;
> +}
> +
> +static inline bool is_in_protected_mode(struct kvm_cpu *vcpu)
> +{
> +	return vcpu->sregs.cr0 & 0x01;
> +}
> +
> +static inline u64 ip_to_flat(struct kvm_cpu *vcpu, u64 ip)
> +{
> +	u64 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(vcpu))
> +		return ip;
> +
> +	cs = vcpu->sregs.cs.selector;
> +
> +	return ip + (cs << 4);
> +}
> +
> +static inline u32 selector_to_base(u16 selector)
> +{
> +	/*
> +	 * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
> +	 */
> +	return (u32)selector * 16;
> +}
> +
> +static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
> +{
> +	struct kvm_cpu *vcpu;
> +
> +	vcpu		= calloc(1, sizeof *vcpu);
> +	if (!vcpu)
> +		return NULL;
> +
> +	vcpu->kvm	= kvm;
> +
> +	return vcpu;
> +}
> +
> +void kvm_cpu__delete(struct kvm_cpu *vcpu)
> +{
> +	if (vcpu->msrs)
> +		free(vcpu->msrs);
> +
> +	free(vcpu);
> +}
> +
> +struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id)
> +{
> +	struct kvm_cpu *vcpu;
> +	int mmap_size;
> +	int coalesced_offset;
> +
> +	vcpu		= kvm_cpu__new(kvm);
> +	if (!vcpu)
> +		return NULL;
> +
> +	vcpu->cpu_id	= cpu_id;
> +
> +	vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
> +	if (vcpu->vcpu_fd < 0)
> +		die_perror("KVM_CREATE_VCPU ioctl");
> +
> +	mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
> +	if (mmap_size < 0)
> +		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
> +
> +	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
> +	if (vcpu->kvm_run == MAP_FAILED)
> +		die("unable to mmap vcpu fd");
> +
> +	coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
> +	if (coalesced_offset)
> +		vcpu->ring = (void *)vcpu->kvm_run + (coalesced_offset * PAGE_SIZE);
> +
> +	vcpu->is_running = true;
> +
> +	return vcpu;
> +}
> +
> +static struct kvm_msrs *kvm_msrs__new(size_t nmsrs)
> +{
> +	struct kvm_msrs *vcpu = calloc(1, sizeof(*vcpu) + (sizeof(struct kvm_msr_entry) * nmsrs));
> +
> +	if (!vcpu)
> +		die("out of memory");
> +
> +	return vcpu;
> +}
> +
> +#define KVM_MSR_ENTRY(_index, _data)	\
> +	(struct kvm_msr_entry) { .index = _index, .data = _data }
> +
> +static void kvm_cpu__setup_msrs(struct kvm_cpu *vcpu)
> +{
> +	unsigned long ndx = 0;
> +
> +	vcpu->msrs = kvm_msrs__new(100);
> +
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_CS,	0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_ESP,	0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_EIP,	0x0);
> +#ifdef CONFIG_X86_64
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_STAR,			0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_CSTAR,			0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_KERNEL_GS_BASE,		0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_SYSCALL_MASK,		0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_LSTAR,			0x0);
> +#endif
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_TSC,		0x0);
> +	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_MISC_ENABLE,
> +						MSR_IA32_MISC_ENABLE_FAST_STRING);
> +
> +	vcpu->msrs->nmsrs	= ndx;
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_SET_MSRS, vcpu->msrs) < 0)
> +		die_perror("KVM_SET_MSRS failed");
> +}
> +
> +static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
> +{
> +	vcpu->fpu = (struct kvm_fpu) {
> +		.fcw		= 0x37f,
> +		.mxcsr		= 0x1f80,
> +	};
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_SET_FPU, &vcpu->fpu) < 0)
> +		die_perror("KVM_SET_FPU failed");
> +}
> +
> +static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
> +{
> +	vcpu->regs = (struct kvm_regs) {
> +		/* We start the guest in 16-bit real mode  */
> +		.rflags		= 0x0000000000000002ULL,
> +
> +		.rip		= vcpu->kvm->boot_ip,
> +		.rsp		= vcpu->kvm->boot_sp,
> +		.rbp		= vcpu->kvm->boot_sp,
> +	};
> +
> +	if (vcpu->regs.rip > USHRT_MAX)
> +		die("ip 0x%llx is too high for real mode", (u64) vcpu->regs.rip);
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
> +		die_perror("KVM_SET_REGS failed");
> +}
> +
> +static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
> +{
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> +		die_perror("KVM_GET_SREGS failed");
> +
> +	vcpu->sregs.cs.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.cs.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.ss.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.ss.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.ds.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.ds.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.es.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.es.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.fs.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.fs.base	= selector_to_base(vcpu->kvm->boot_selector);
> +	vcpu->sregs.gs.selector	= vcpu->kvm->boot_selector;
> +	vcpu->sregs.gs.base	= selector_to_base(vcpu->kvm->boot_selector);
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_SET_SREGS, &vcpu->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 *vcpu)
> +{
> +	kvm_cpu__setup_cpuid(vcpu);
> +	kvm_cpu__setup_sregs(vcpu);
> +	kvm_cpu__setup_regs(vcpu);
> +	kvm_cpu__setup_fpu(vcpu);
> +	kvm_cpu__setup_msrs(vcpu);
> +}
> +
> +static void print_dtable(const char *name, struct kvm_dtable *dtable)
> +{
> +	dprintf(debug_fd, " %s                 %016llx  %08hx\n",
> +		name, (u64) dtable->base, (u16) dtable->limit);
> +}
> +
> +static void print_segment(const char *name, struct kvm_segment *seg)
> +{
> +	dprintf(debug_fd, " %s       %04hx      %016llx  %08x  %02hhx    %x %x   %x  %x %x %x %x\n",
> +		name, (u16) seg->selector, (u64) seg->base, (u32) seg->limit,
> +		(u8) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
> +}
> +
> +void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
> +{
> +	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(vcpu->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;
> +
> +	dprintf(debug_fd, "\n Registers:\n");
> +	dprintf(debug_fd,   " ----------\n");
> +	dprintf(debug_fd, " rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
> +	dprintf(debug_fd, " rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
> +	dprintf(debug_fd, " rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
> +	dprintf(debug_fd, " rbp: %016lx    r8: %016lx    r9: %016lx\n", rbp, r8,  r9);
> +	dprintf(debug_fd, " r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
> +	dprintf(debug_fd, " r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
> +
> +	if (ioctl(vcpu->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;
> +
> +	dprintf(debug_fd, " cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
> +	dprintf(debug_fd, " cr4: %016lx   cr8: %016lx\n", cr4, cr8);
> +	dprintf(debug_fd, "\n Segment registers:\n");
> +	dprintf(debug_fd,   " ------------------\n");
> +	dprintf(debug_fd, " 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);
> +
> +	dprintf(debug_fd, "\n APIC:\n");
> +	dprintf(debug_fd,   " -----\n");
> +	dprintf(debug_fd, " efer: %016llx  apic base: %016llx  nmi: %s\n",
> +		(u64) sregs.efer, (u64) sregs.apic_base,
> +		(vcpu->kvm->nmi_disabled ? "disabled" : "enabled"));
> +
> +	dprintf(debug_fd, "\n Interrupt bitmap:\n");
> +	dprintf(debug_fd,   " -----------------\n");
> +	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
> +		dprintf(debug_fd, " %016llx", (u64) sregs.interrupt_bitmap[i]);
> +	dprintf(debug_fd, "\n");
> +}
> +
> +#define MAX_SYM_LEN		128
> +
> +void kvm_cpu__show_code(struct kvm_cpu *vcpu)
> +{
> +	unsigned int code_bytes = 64;
> +	unsigned int code_prologue = code_bytes * 43 / 64;
> +	unsigned int code_len = code_bytes;
> +	char sym[MAX_SYM_LEN];
> +	unsigned char c;
> +	unsigned int i;
> +	u8 *ip;
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
> +		die("KVM_GET_REGS failed");
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> +		die("KVM_GET_SREGS failed");
> +
> +	ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip) - code_prologue);
> +
> +	dprintf(debug_fd, "\n Code:\n");
> +	dprintf(debug_fd,   " -----\n");
> +
> +	symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
> +
> +	dprintf(debug_fd, " rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
> +
> +	for (i = 0; i < code_len; i++, ip++) {
> +		if (!host_ptr_in_ram(vcpu->kvm, ip))
> +			break;
> +
> +		c = *ip;
> +
> +		if (ip == guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip)))
> +			dprintf(debug_fd, " <%02x>", c);
> +		else
> +			dprintf(debug_fd, " %02x", c);
> +	}
> +
> +	dprintf(debug_fd, "\n");
> +
> +	dprintf(debug_fd, "\n Stack:\n");
> +	dprintf(debug_fd,   " ------\n");
> +	kvm__dump_mem(vcpu->kvm, vcpu->regs.rsp, 32);
> +}
> +
> +void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
> +{
> +	u64 *pte1;
> +	u64 *pte2;
> +	u64 *pte3;
> +	u64 *pte4;
> +
> +	if (!is_in_protected_mode(vcpu))
> +		return;
> +
> +	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
> +		die("KVM_GET_SREGS failed");
> +
> +	pte4	= guest_flat_to_host(vcpu->kvm, vcpu->sregs.cr3);
> +	if (!host_ptr_in_ram(vcpu->kvm, pte4))
> +		return;
> +
> +	pte3	= guest_flat_to_host(vcpu->kvm, (*pte4 & ~0xfff));
> +	if (!host_ptr_in_ram(vcpu->kvm, pte3))
> +		return;
> +
> +	pte2	= guest_flat_to_host(vcpu->kvm, (*pte3 & ~0xfff));
> +	if (!host_ptr_in_ram(vcpu->kvm, pte2))
> +		return;
> +
> +	pte1	= guest_flat_to_host(vcpu->kvm, (*pte2 & ~0xfff));
> +	if (!host_ptr_in_ram(vcpu->kvm, pte1))
> +		return;
> +
> +	dprintf(debug_fd, "Page Tables:\n");
> +	if (*pte2 & (1 << 7))
> +		dprintf(debug_fd, " pte4: %016llx   pte3: %016llx"
> +			"   pte2: %016llx\n",
> +			*pte4, *pte3, *pte2);
> +	else
> +		dprintf(debug_fd, " pte4: %016llx  pte3: %016llx   pte2: %016"
> +			"llx   pte1: %016llx\n",
> +			*pte4, *pte3, *pte2, *pte1);
> +}
> diff --git a/tools/kvm/x86/kvm.c b/tools/kvm/x86/kvm.c
> new file mode 100644
> index 0000000..ac6c91e
> --- /dev/null
> +++ b/tools/kvm/x86/kvm.c
> @@ -0,0 +1,330 @@
> +#include "kvm/kvm.h"
> +#include "kvm/boot-protocol.h"
> +#include "kvm/cpufeature.h"
> +#include "kvm/interrupt.h"
> +#include "kvm/mptable.h"
> +#include "kvm/util.h"
> +
> +#include <asm/bootparam.h>
> +#include <linux/kvm.h>
> +
> +#include <sys/types.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <sys/stat.h>
> +#include <stdbool.h>
> +#include <assert.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <fcntl.h>
> +#include <asm/unistd.h>
> +
> +struct kvm_ext kvm_req_ext[] = {
> +	{ DEFINE_KVM_EXT(KVM_CAP_COALESCED_MMIO) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_SET_TSS_ADDR) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_PIT2) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_USER_MEMORY) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_ROUTING) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_HLT) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_INJECT_STATUS) },
> +	{ DEFINE_KVM_EXT(KVM_CAP_EXT_CPUID) },
> +	{ 0, 0 }
> +};
> +
> +bool kvm__arch_cpu_supports_vm(void)
> +{
> +	struct cpuid_regs regs;
> +	u32 eax_base;
> +	int feature;
> +
> +	regs	= (struct cpuid_regs) {
> +		.eax		= 0x00,
> +	};
> +	host_cpuid(&regs);
> +
> +	switch (regs.ebx) {
> +	case CPUID_VENDOR_INTEL_1:
> +		eax_base	= 0x00;
> +		feature		= KVM__X86_FEATURE_VMX;
> +		break;
> +
> +	case CPUID_VENDOR_AMD_1:
> +		eax_base	= 0x80000000;
> +		feature		= KVM__X86_FEATURE_SVM;
> +		break;
> +
> +	default:
> +		return false;
> +	}
> +
> +	regs	= (struct cpuid_regs) {
> +		.eax		= eax_base,
> +	};
> +	host_cpuid(&regs);
> +
> +	if (regs.eax < eax_base + 0x01)
> +		return false;
> +
> +	regs	= (struct cpuid_regs) {
> +		.eax		= eax_base + 0x01
> +	};
> +	host_cpuid(&regs);
> +
> +	return regs.ecx & (1 << feature);
> +}
> +
> +/*
> + * Allocating RAM size bigger than 4GB requires us to leave a gap
> + * in the RAM which is used for PCI MMIO, hotplug, and unconfigured
> + * devices (see documentation of e820_setup_gap() for details).
> + *
> + * If we're required to initialize RAM bigger than 4GB, we will create
> + * a gap between 0xe0000000 and 0x100000000 in the guest virtual mem space.
> + */
> +
> +void kvm__init_ram(struct kvm *kvm)
> +{
> +	u64	phys_start, phys_size;
> +	void	*host_mem;
> +
> +	if (kvm->ram_size < KVM_32BIT_GAP_START) {
> +		/* Use a single block of RAM for 32bit RAM */
> +
> +		phys_start = 0;
> +		phys_size  = kvm->ram_size;
> +		host_mem   = kvm->ram_start;
> +
> +		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> +	} else {
> +		/* First RAM range from zero to the PCI gap: */
> +
> +		phys_start = 0;
> +		phys_size  = KVM_32BIT_GAP_START;
> +		host_mem   = kvm->ram_start;
> +
> +		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> +
> +		/* Second RAM range from 4GB to the end of RAM: */
> +
> +		phys_start = 0x100000000ULL;
> +		phys_size  = kvm->ram_size - phys_size;
> +		host_mem   = kvm->ram_start + phys_start;
> +
> +		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> +	}
> +}
> +
> +/* Architecture-specific KVM init */
> +void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, u64 ram_size, const char *name)
> +{
> +	struct kvm_pit_config pit_config = { .flags = 0, };
> +	int ret;
> +
> +	ret = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
> +	if (ret < 0)
> +		die_perror("KVM_SET_TSS_ADDR ioctl");
> +
> +	ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config);
> +	if (ret < 0)
> +		die_perror("KVM_CREATE_PIT2 ioctl");
> +
> +	kvm->ram_size		= ram_size;
> +
> +	if (kvm->ram_size < KVM_32BIT_GAP_START) {
> +		kvm->ram_start = mmap(NULL, ram_size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
> +	} else {
> +		kvm->ram_start = mmap(NULL, ram_size + KVM_32BIT_GAP_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
> +		if (kvm->ram_start != MAP_FAILED) {
> +			/*
> +			 * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
> +			 * if we accidently write to it, we will know.
> +			 */
> +			mprotect(kvm->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
> +		}
> +	}
> +	if (kvm->ram_start == MAP_FAILED)
> +		die("out of memory");
> +
> +	madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
> +
> +	ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
> +	if (ret < 0)
> +		die_perror("KVM_CREATE_IRQCHIP ioctl");
> +}
> +
> +void kvm__irq_line(struct kvm *kvm, int irq, int level)
> +{
> +	struct kvm_irq_level irq_level;
> +
> +	irq_level	= (struct kvm_irq_level) {
> +		{
> +			.irq		= irq,
> +		},
> +		.level		= level,
> +	};
> +
> +	if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
> +		die_perror("KVM_IRQ_LINE failed");
> +}
> +
> +void kvm__irq_trigger(struct kvm *kvm, int irq)
> +{
> +	kvm__irq_line(kvm, irq, 1);
> +	kvm__irq_line(kvm, irq, 0);
> +}
> +
> +#define BOOT_LOADER_SELECTOR	0x1000
> +#define BOOT_LOADER_IP		0x0000
> +#define BOOT_LOADER_SP		0x8000
> +#define BOOT_CMDLINE_OFFSET	0x20000
> +
> +#define BOOT_PROTOCOL_REQUIRED	0x206
> +#define LOAD_HIGH		0x01
> +
> +int load_flat_binary(struct kvm *kvm, int fd)
> +{
> +	void *p;
> +	int nr;
> +
> +	if (lseek(fd, 0, SEEK_SET) < 0)
> +		die_perror("lseek");
> +
> +	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
> +
> +	while ((nr = read(fd, p, 65536)) > 0)
> +		p += nr;
> +
> +	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
> +	kvm->boot_ip		= BOOT_LOADER_IP;
> +	kvm->boot_sp		= BOOT_LOADER_SP;
> +
> +	return true;
> +}
> +
> +static const char *BZIMAGE_MAGIC	= "HdrS";
> +
> +bool load_bzimage(struct kvm *kvm, int fd_kernel,
> +		  int fd_initrd, const char *kernel_cmdline, u16 vidmode)
> +{
> +	struct boot_params *kern_boot;
> +	unsigned long setup_sects;
> +	struct boot_params boot;
> +	size_t cmdline_size;
> +	ssize_t setup_size;
> +	void *p;
> +	int nr;
> +
> +	/*
> +	 * See Documentation/x86/boot.txt for details no bzImage on-disk and
> +	 * memory layout.
> +	 */
> +
> +	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> +		die_perror("lseek");
> +
> +	if (read(fd_kernel, &boot, sizeof(boot)) != sizeof(boot))
> +		return false;
> +
> +	if (memcmp(&boot.hdr.header, BZIMAGE_MAGIC, strlen(BZIMAGE_MAGIC)))
> +		return false;
> +
> +	if (boot.hdr.version < BOOT_PROTOCOL_REQUIRED)
> +		die("Too old kernel");
> +
> +	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> +		die_perror("lseek");
> +
> +	if (!boot.hdr.setup_sects)
> +		boot.hdr.setup_sects = BZ_DEFAULT_SETUP_SECTS;
> +	setup_sects = boot.hdr.setup_sects + 1;
> +
> +	setup_size = setup_sects << 9;
> +	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
> +
> +	/* copy setup.bin to mem*/
> +	if (read(fd_kernel, p, setup_size) != setup_size)
> +		die_perror("read");
> +
> +	/* copy vmlinux.bin to BZ_KERNEL_START*/
> +	p = guest_flat_to_host(kvm, BZ_KERNEL_START);
> +
> +	while ((nr = read(fd_kernel, p, 65536)) > 0)
> +		p += nr;
> +
> +	p = guest_flat_to_host(kvm, BOOT_CMDLINE_OFFSET);
> +	if (kernel_cmdline) {
> +		cmdline_size = strlen(kernel_cmdline) + 1;
> +		if (cmdline_size > boot.hdr.cmdline_size)
> +			cmdline_size = boot.hdr.cmdline_size;
> +
> +		memset(p, 0, boot.hdr.cmdline_size);
> +		memcpy(p, kernel_cmdline, cmdline_size - 1);
> +	}
> +
> +	kern_boot	= guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, 0x00);
> +
> +	kern_boot->hdr.cmd_line_ptr	= BOOT_CMDLINE_OFFSET;
> +	kern_boot->hdr.type_of_loader	= 0xff;
> +	kern_boot->hdr.heap_end_ptr	= 0xfe00;
> +	kern_boot->hdr.loadflags	|= CAN_USE_HEAP;
> +	kern_boot->hdr.vid_mode		= vidmode;
> +
> +	/*
> +	 * Read initrd image into guest memory
> +	 */
> +	if (fd_initrd >= 0) {
> +		struct stat initrd_stat;
> +		unsigned long addr;
> +
> +		if (fstat(fd_initrd, &initrd_stat))
> +			die_perror("fstat");
> +
> +		addr = boot.hdr.initrd_addr_max & ~0xfffff;
> +		for (;;) {
> +			if (addr < BZ_KERNEL_START)
> +				die("Not enough memory for initrd");
> +			else if (addr < (kvm->ram_size - initrd_stat.st_size))
> +				break;
> +			addr -= 0x100000;
> +		}
> +
> +		p = guest_flat_to_host(kvm, addr);
> +		nr = read(fd_initrd, p, initrd_stat.st_size);
> +		if (nr != initrd_stat.st_size)
> +			die("Failed to read initrd");
> +
> +		kern_boot->hdr.ramdisk_image	= addr;
> +		kern_boot->hdr.ramdisk_size	= initrd_stat.st_size;
> +	}
> +
> +	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
> +	/*
> +	 * The real-mode setup code starts at offset 0x200 of a bzImage. See
> +	 * Documentation/x86/boot.txt for details.
> +	 */
> +	kvm->boot_ip		= BOOT_LOADER_IP + 0x200;
> +	kvm->boot_sp		= BOOT_LOADER_SP;
> +
> +	return true;
> +}
> +
> +/**
> + * kvm__arch_setup_firmware - inject BIOS into guest system memory
> + * @kvm - guest system descriptor
> + *
> + * This function is a main routine where we poke guest memory
> + * and install BIOS there.
> + */
> +void kvm__arch_setup_firmware(struct kvm *kvm)
> +{
> +	/* standart minimal configuration */
> +	setup_bios(kvm);
> +
> +	/* FIXME: SMP, ACPI and friends here */
> +
> +	/* MP table */
> +	mptable_setup(kvm, kvm->nrcpus);
> +}
> diff --git a/tools/kvm/mptable.c b/tools/kvm/x86/mptable.c
> similarity index 100%
> rename from tools/kvm/mptable.c
> rename to tools/kvm/x86/mptable.c
> --
> 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

-- 

Sasha.

  reply	other threads:[~2011-12-06  8:07 UTC|newest]

Thread overview: 210+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <cover.1323141075.git.matt@ozlabs.org>
2011-12-06  3:37 ` [PATCH 01/28] kvm tools: Split x86 arch-specific bits into x86/ Matt Evans
2011-12-06  3:37   ` Matt Evans
2011-12-06  8:07   ` Sasha Levin [this message]
2011-12-06  8:07     ` Sasha Levin
2011-12-06 10:10     ` Pekka Enberg
2011-12-06 10:10       ` Pekka Enberg
2011-12-06  3:37 ` [PATCH 02/28] kvm tools: Only build/init i8042 on x86 Matt Evans
2011-12-06  3:37   ` Matt Evans
2011-12-06  8:11   ` Sasha Levin
2011-12-06  8:11     ` Sasha Levin
2011-12-06 18:59   ` Scott Wood
2011-12-06 18:59     ` Scott Wood
2011-12-07  7:39     ` Matt Evans
2011-12-07  7:39       ` Matt Evans
2011-12-06  3:37 ` [PATCH 03/28] kvm tools: Add Makefile parameter for kernel include Matt Evans
2011-12-06  3:37   ` [PATCH 03/28] kvm tools: Add Makefile parameter for kernel include path Matt Evans
2011-12-06  3:38 ` [PATCH 04/28] kvm tools: Re-arrange Makefile to heed CFLAGS before Matt Evans
2011-12-06  3:38   ` [PATCH 04/28] kvm tools: Re-arrange Makefile to heed CFLAGS before checking for optional libs Matt Evans
2011-12-06  3:38 ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Matt Evans
2011-12-06  3:38   ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Matt Evans
2011-12-06  8:13   ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when Sasha Levin
2011-12-06  8:13     ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Sasha Levin
2011-12-06  8:28     ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Ingo Molnar
2011-12-06  8:28       ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Ingo Molnar
2011-12-06 10:05       ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Paul Mackerras
2011-12-06 10:05         ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Paul Mackerras
2011-12-06 10:24         ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Ingo Molnar
2011-12-06 10:24           ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Ingo Molnar
2011-12-07  7:01           ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Matt Evans
2011-12-07  7:01             ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Matt Evans
2011-12-07  8:16             ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Ingo Molnar
2011-12-07  8:16               ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Ingo Molnar
2011-12-07 12:49               ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Paolo Bonzini
2011-12-07 12:49                 ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Paolo Bonzini
2011-12-07 17:21                 ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Pekka Enberg
2011-12-07 17:21                   ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Pekka Enberg
2011-12-07 17:14               ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Pekka Enberg
2011-12-07 17:14                 ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Pekka Enberg
2011-12-08  3:14                 ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Matt Evans
2011-12-08  3:14                   ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Matt Evans
2011-12-08  4:49                   ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Ingo Molnar
2011-12-08  4:49                     ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Ingo Molnar
2011-12-08  4:56                     ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Matt Evans
2011-12-08  4:56                       ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Matt Evans
2011-12-08  5:47                       ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Matt Evans
2011-12-08  5:47                         ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Matt Evans
2011-12-08  5:49                         ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Ingo Molnar
2011-12-08  5:49                           ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Ingo Molnar
2011-12-08  6:17                           ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing Matt Evans
2011-12-08  6:17                             ` [PATCH 05/28] kvm tools: 64-bit tidy; use PRIx64 when printf'ing u64s and link appropriately Matt Evans
2011-12-06  3:39 ` [PATCH 06/28] kvm tools: Add arch-specific KVM_RUN exit handling Matt Evans
2011-12-06  3:39   ` [PATCH 06/28] kvm tools: Add arch-specific KVM_RUN exit handling via kvm_cpu__handle_exit() Matt Evans
2011-12-06  3:39 ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific Matt Evans
2011-12-06  3:39   ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Matt Evans
2011-12-06  8:20   ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to Sasha Levin
2011-12-06  8:20     ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Sasha Levin
2011-12-07  6:17     ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific Matt Evans
2011-12-07  6:17       ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Matt Evans
2011-12-07  6:34       ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to Sasha Levin
2011-12-07  6:34         ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Sasha Levin
2011-12-07  7:19         ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific Matt Evans
2011-12-07  7:19           ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Matt Evans
2011-12-07  7:24           ` Alexander Graf
2011-12-07  7:24             ` Alexander Graf
2011-12-07  7:28             ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific Matt Evans
2011-12-07  7:28               ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Matt Evans
2011-12-07  8:29               ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to Sasha Levin
2011-12-07  8:29                 ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Sasha Levin
2011-12-07 14:11                 ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific Avi Kivity
2011-12-07 14:11                   ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Avi Kivity
2011-12-07 14:22                   ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to Sasha Levin
2011-12-07 14:22                     ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Sasha Levin
2011-12-07 14:25                     ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific Avi Kivity
2011-12-07 14:25                       ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Avi Kivity
2011-12-07 15:00                       ` Alexander Graf
2011-12-07 15:00                         ` Alexander Graf
2011-12-07 15:25                         ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to Sasha Levin
2011-12-07 15:25                           ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Sasha Levin
2011-12-07 15:58                           ` Alexander Graf
2011-12-07 15:58                             ` Alexander Graf
2011-12-20 15:23                 ` Alexander Graf
2011-12-20 15:23                   ` Alexander Graf
2011-12-21 22:17                   ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to Paul Mackerras
2011-12-21 22:17                     ` [PATCH 07/28] kvm tools: Move 'kvm__recommended_cpus' to arch-specific code Paul Mackerras
2011-12-23 14:05                     ` Alexander Graf
2011-12-23 14:05                       ` Alexander Graf
2011-12-20 15:20           ` Alexander Graf
2011-12-20 15:20             ` Alexander Graf
2011-12-06  3:39 ` [PATCH 08/28] kvm tools: Fix KVM_RUN exit code check Matt Evans
2011-12-06  3:39   ` Matt Evans
2011-12-06  8:22   ` Sasha Levin
2011-12-06  8:22     ` Sasha Levin
2011-12-07  0:32     ` Matt Evans
2011-12-07  0:32       ` Matt Evans
2011-12-07  6:44       ` Alexander Graf
2011-12-07  6:44         ` Alexander Graf
2011-12-07 14:12         ` Avi Kivity
2011-12-07 14:12           ` Avi Kivity
2011-12-07 15:01           ` Alexander Graf
2011-12-07 15:01             ` Alexander Graf
2011-12-07 15:05             ` Avi Kivity
2011-12-07 15:05               ` Avi Kivity
2011-12-08  3:03     ` Matt Evans
2011-12-08  3:03       ` Matt Evans
2011-12-08  5:31       ` Sasha Levin
2011-12-08  5:31         ` Sasha Levin
2011-12-22 10:03         ` Avi Kivity
2011-12-22 10:03           ` Avi Kivity
2011-12-22 10:18           ` Sasha Levin
2011-12-22 10:18             ` Sasha Levin
2011-12-22 10:21             ` Avi Kivity
2011-12-22 10:21               ` Avi Kivity
2011-12-22 10:34               ` Sasha Levin
2011-12-22 10:34                 ` Sasha Levin
2011-12-06  3:39 ` [PATCH 09/28] kvm tools: Add kvm__arch_periodic_poll() Matt Evans
2011-12-06  3:39   ` Matt Evans
2011-12-06  3:40 ` [PATCH 10/28] kvm tools: term.h needs to include stdbool.h Matt Evans
2011-12-06  3:40   ` Matt Evans
2011-12-06  3:40 ` [PATCH 11/28] kvm tools: kvm.c needs to include sys/stat.h for mkdir Matt Evans
2011-12-06  3:40   ` Matt Evans
2011-12-06  3:40 ` [PATCH 12/28] kvm tools: Move arch-specific cmdline init into kvm__arch_set_cmdline() Matt Evans
2011-12-06  3:40   ` Matt Evans
2011-12-06  3:40 ` [PATCH 13/28] kvm tools: Add CONSOLE_HV term type and allow it to Matt Evans
2011-12-06  3:40   ` [PATCH 13/28] kvm tools: Add CONSOLE_HV term type and allow it to be selected Matt Evans
2011-12-06  3:40 ` [PATCH 14/28] kvm tools: Fix term_getc(), term_getc_iov() endian Matt Evans
2011-12-06  3:40   ` [PATCH 14/28] kvm tools: Fix term_getc(), term_getc_iov() endian bugs Matt Evans
2011-12-06 10:24   ` Pekka Enberg
2011-12-06 10:24     ` Pekka Enberg
2011-12-06 12:00     ` [PATCH 14/28] kvm tools: Fix term_getc(), term_getc_iov() endian Asias He
2011-12-06 12:00       ` [PATCH 14/28] kvm tools: Fix term_getc(), term_getc_iov() endian bugs Asias He
2011-12-07  2:39       ` [PATCH 14/28] kvm tools: Fix term_getc(), term_getc_iov() endian Matt Evans
2011-12-07  2:39         ` [PATCH 14/28] kvm tools: Fix term_getc(), term_getc_iov() endian bugs Matt Evans
2011-12-06  3:40 ` [PATCH 15/28] kvm tools: Allow initrd_check() to match a cpio Matt Evans
2011-12-06  3:40   ` Matt Evans
2011-12-06 10:26   ` Pekka Enberg
2011-12-06 10:26     ` Pekka Enberg
2011-12-06  3:41 ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an initrd Matt Evans
2011-12-06  3:41   ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an initrd alongside Matt Evans
2011-12-06 10:29   ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an Pekka Enberg
2011-12-06 10:29     ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an initrd alongside Pekka Enberg
2011-12-06 12:04     ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an Cyrill Gorcunov
2011-12-06 12:04       ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an initrd alongside Cyrill Gorcunov
2011-12-07  0:42       ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an Matt Evans
2011-12-07  0:42         ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an initrd alongside Matt Evans
2011-12-07  6:33         ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an Cyrill Gorcunov
2011-12-07  6:33           ` [PATCH 16/28] kvm tools: Allow load_flat_binary() to load an initrd alongside Cyrill Gorcunov
2011-12-06  3:41 ` [PATCH 17/28] kvm tools: Only call symbol__init() if we have BFD Matt Evans
2011-12-06  3:41   ` Matt Evans
2011-12-06  8:26   ` Sasha Levin
2011-12-06  8:26     ` Sasha Levin
2011-12-07  3:03     ` [PATCH 17/28] kvm tools: Only call symbol__init() if we have Matt Evans
2011-12-07  3:03       ` [PATCH 17/28] kvm tools: Only call symbol__init() if we have BFD Matt Evans
2011-12-06  3:41 ` [PATCH 18/28] kvm tools: Initialise PCI before devices start getting Matt Evans
2011-12-06  3:41   ` [PATCH 18/28] kvm tools: Initialise PCI before devices start getting registered with PCI Matt Evans
2011-12-06  3:41 ` [PATCH 19/28] kvm tools: Perform CPU and firmware setup after devices Matt Evans
2011-12-06  3:41   ` [PATCH 19/28] kvm tools: Perform CPU and firmware setup after devices are added Matt Evans
2011-12-06  3:41 ` [PATCH 20/28] kvm tools: Init IRQs after determining nrcpus Matt Evans
2011-12-06  3:41   ` Matt Evans
2011-12-06  3:41 ` [PATCH 21/28] kvm tools: Add --hugetlbfs option to specify memory Matt Evans
2011-12-06  3:41   ` [PATCH 21/28] kvm tools: Add --hugetlbfs option to specify memory path Matt Evans
2011-12-06  8:32   ` [PATCH 21/28] kvm tools: Add --hugetlbfs option to specify Sasha Levin
2011-12-06  8:32     ` [PATCH 21/28] kvm tools: Add --hugetlbfs option to specify memory path Sasha Levin
2011-12-07  0:35     ` [PATCH 21/28] kvm tools: Add --hugetlbfs option to specify memory Matt Evans
2011-12-07  0:35       ` [PATCH 21/28] kvm tools: Add --hugetlbfs option to specify memory path Matt Evans
2011-12-07  6:01       ` [PATCH 21/28] kvm tools: Add --hugetlbfs option to specify Sasha Levin
2011-12-07  6:01         ` [PATCH 21/28] kvm tools: Add --hugetlbfs option to specify memory path Sasha Levin
2011-12-06  3:42 ` [PATCH 22/28] kvm tools: Move PCI_MAX_DEVICES to pci.h Matt Evans
2011-12-06  3:42   ` Matt Evans
2011-12-06  3:42 ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device setup Matt Evans
2011-12-06  3:42   ` Matt Evans
2011-12-06 10:25   ` Pekka Enberg
2011-12-06 10:25     ` Pekka Enberg
2011-12-06 10:28     ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device Cyrill Gorcunov
2011-12-06 10:28       ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device setup Cyrill Gorcunov
2011-12-06 11:41       ` Pekka Enberg
2011-12-06 11:41         ` Pekka Enberg
2011-12-06 11:47         ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device Cyrill Gorcunov
2011-12-06 11:47           ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device setup Cyrill Gorcunov
2011-12-06 11:58           ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device Pekka Enberg
2011-12-06 11:58             ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device setup Pekka Enberg
2011-12-06 12:10             ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device Cyrill Gorcunov
2011-12-06 12:10               ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device setup Cyrill Gorcunov
2011-12-06 13:29               ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device Pekka Enberg
2011-12-06 13:29                 ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device setup Pekka Enberg
2011-12-06 13:38                 ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device Cyrill Gorcunov
2011-12-06 13:38                   ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device setup Cyrill Gorcunov
2011-12-07  2:58                   ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device Matt Evans
2011-12-07  2:58                     ` [PATCH 23/28] kvm tools: Endian-sanitise pci.h and PCI device setup Matt Evans
2011-12-06  3:42 ` [PATCH 24/28] kvm tools: Fix virtio-pci endian bug when reading VIRTIO_PCI_QUEUE_NUM Matt Evans
2011-12-06  3:42   ` Matt Evans
2011-12-06 10:26   ` Pekka Enberg
2011-12-06 10:26     ` Pekka Enberg
2011-12-06 11:28     ` [PATCH 24/28] kvm tools: Fix virtio-pci endian bug when reading Asias He
2011-12-06 11:28       ` [PATCH 24/28] kvm tools: Fix virtio-pci endian bug when reading VIRTIO_PCI_QUEUE_NUM Asias He
2011-12-06 11:39       ` Pekka Enberg
2011-12-06 11:39         ` Pekka Enberg
2011-12-06 13:15     ` [PATCH 24/28] kvm tools: Fix virtio-pci endian bug when reading Sasha Levin
2011-12-06 13:15       ` [PATCH 24/28] kvm tools: Fix virtio-pci endian bug when reading VIRTIO_PCI_QUEUE_NUM Sasha Levin
2011-12-06  3:42 ` [PATCH 25/28] kvm tools: Correctly set virtio-pci bar_size and remove Matt Evans
2011-12-06  3:42   ` [PATCH 25/28] kvm tools: Correctly set virtio-pci bar_size and remove hardwired address Matt Evans
2011-12-06  3:42 ` [PATCH 26/28] kvm tools: Add pci__config_{rd,wr}(), pci__find_dev() Matt Evans
2011-12-06  3:42   ` [PATCH 26/28] kvm tools: Add pci__config_{rd,wr}(), pci__find_dev() and fix PCI config register addressing Matt Evans
2011-12-06  3:43 ` [PATCH 27/28] kvm tools: Arch-specific define for PCI MMIO allocation Matt Evans
2011-12-06  3:43   ` [PATCH 27/28] kvm tools: Arch-specific define for PCI MMIO allocation area Matt Evans
2011-12-06  3:43 ` [PATCH 28/28] kvm tools: Create arch-specific kvm_cpu__emulate_io() Matt Evans
2011-12-06  3:43   ` Matt Evans
2011-12-06  8:54   ` [PATCH 28/28] kvm tools: Create arch-specific Sasha Levin
2011-12-06  8:54     ` [PATCH 28/28] kvm tools: Create arch-specific kvm_cpu__emulate_io() Sasha Levin
2011-12-07  6:36     ` Matt Evans
2011-12-07  6:36       ` Matt Evans

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1323158866.3882.2.camel@lappy \
    --to=levinsasha928@gmail.com \
    --cc=kvm-ppc@vger.kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=matt@ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.