All of lore.kernel.org
 help / color / mirror / Atom feed
* [1-5/17] Patch 1-10 of kvm/ia64 V2
@ 2007-12-20  5:46 Zhang, Xiantao
       [not found] ` <42DFA526FC41B1429CE7279EF83C6BDCB139D3-wq7ZOvIWXbMAbVU2wMM1CrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Zhang, Xiantao @ 2007-12-20  5:46 UTC (permalink / raw)
  To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: Luck, Tony, linux-ia64-u79uwXL29TY76Z2rM5mHXA, Avi Kivity

[-- Attachment #1: Type: text/plain, Size: 345 bytes --]

> [1/17] Add kvm.h, kvm_para.h and kvm_host.h for ia64.
> [2/17] Add kvm-ia64.c to support kvm module on Itanium processors.
> [3/17] Add firmware virtualization support.
> [4/17] Add TR operation routines.
> [5/17] Add some header files for kvm use.

Signed-off-by : Zhang Xiantao (xiantao.zhang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org)

[-- Attachment #2: 0001-kvm-ia64-Add-header-files-for-ia64.patch --]
[-- Type: application/octet-stream, Size: 16724 bytes --]

From f8ef376f39174f5a13804b17443d358aaa882036 Mon Sep 17 00:00:00 2001
From: Zhang Xiantao <xiantao.zhang@intel.com>
Date: Wed, 19 Dec 2007 14:02:27 +0800
Subject: [PATCH] kvm/ia64: Add header files for ia64.

This patches add kvm.h , kvm_para.h, and kvm_host.h in include/asm-ia64.
Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com>
---
 include/asm-ia64/kvm.h      |   65 ++++++
 include/asm-ia64/kvm_host.h |  495 +++++++++++++++++++++++++++++++++++++++++++
 include/asm-ia64/kvm_para.h |    9 +
 3 files changed, 569 insertions(+), 0 deletions(-)
 create mode 100644 include/asm-ia64/kvm.h
 create mode 100644 include/asm-ia64/kvm_host.h
 create mode 100644 include/asm-ia64/kvm_para.h

diff --git a/include/asm-ia64/kvm.h b/include/asm-ia64/kvm.h
new file mode 100644
index 0000000..0dc2253
--- /dev/null
+++ b/include/asm-ia64/kvm.h
@@ -0,0 +1,65 @@
+#ifndef __ASM_KVM_IA64_H
+#define __ASM_KVM_IA64_H
+
+/*
+ * asm-ia64/kvm.h: kvm structure definitions  for ia64
+ *
+ * Copyright (C) 2007 Zhang Xiantao <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <asm/types.h>
+#include <linux/ioctl.h>
+
+/* Architectural interrupt line count. */
+#define KVM_NR_INTERRUPTS 256
+
+#define KVM_IOAPIC_NUM_PINS  24
+struct kvm_ioapic_state {
+	__u64 base_address;
+	__u32 ioregsel;
+	__u32 id;
+	__u32 irr;
+	__u32 pad;
+	union {
+		__u64 bits;
+		struct {
+			__u8 vector;
+			__u8 delivery_mode:3;
+			__u8 dest_mode:1;
+			__u8 delivery_status:1;
+			__u8 polarity:1;
+			__u8 remote_irr:1;
+			__u8 trig_mode:1;
+			__u8 mask:1;
+			__u8 reserve:7;
+			__u8 reserved[4];
+			__u8 dest_id;
+		} fields;
+	} redirtbl[KVM_IOAPIC_NUM_PINS];
+};
+
+#define KVM_IRQCHIP_PIC_MASTER   0
+#define KVM_IRQCHIP_PIC_SLAVE    1
+#define KVM_IRQCHIP_IOAPIC       2
+
+struct kvm_regs {
+};
+
+struct kvm_sregs {
+};
+
+#endif
diff --git a/include/asm-ia64/kvm_host.h b/include/asm-ia64/kvm_host.h
new file mode 100644
index 0000000..17200c5
--- /dev/null
+++ b/include/asm-ia64/kvm_host.h
@@ -0,0 +1,495 @@
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
+/*
+ * ia64.h: used for kvm module, and hold ia64-specific sections.
+ *
+ * Copyright (C) 2007, Intel Corporation.
+ *
+ * Zhang Xiantao <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#ifndef __ASM_KVM_HOST_H
+#define __ASM_KVM_HOST_H
+
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/kvm.h>
+#include <linux/kvm_para.h>
+#include <linux/kvm_types.h>
+
+#include <asm/pal.h>
+#include <asm/sal.h>
+#include <asm/fpu.h>
+
+/* define exit reasons from vmm to kvm*/
+#define EXIT_REASON_VM_PANIC           0
+#define EXIT_REASON_IO_INSTRUCTION     1
+#define EXIT_REASON_MMIO_INSTRUCTION   2
+#define EXIT_REASON_PAL_CALL           3
+#define EXIT_REASON_SAL_CALL           4
+#define EXIT_REASON_SWITCH_RR6         5
+#define EXIT_REASON_VM_DESTROY         7
+#define EXIT_REASON_EXTERNAL_INTERRUPT 8
+#define EXIT_REASON_IPI		       9
+
+/*Define vmm address space and vm data space.*/
+#define KVM_VMM_SIZE (16UL<<20)
+#define KVM_VMM_SHIFT 24
+#define KVM_VMM_BASE 0xD000000000000000UL
+#define VMM_SIZE (8UL<<20)
+
+/*
+ * Define vm_buffer, used by PAL Services, base address.
+ * Note: vmbuffer is in the VMM-BLOCK, the size must be < 8M
+ */
+#define KVM_VM_BUFFER_BASE (KVM_VMM_BASE + VMM_SIZE)
+#define KVM_VM_BUFFER_SIZE (8UL<<20)
+
+/*Define Virtual machine data layout.*/
+#define KVM_VM_DATA_SHIFT  24
+#define KVM_VM_DATA_SIZE (1UL << KVM_VM_DATA_SHIFT)
+#define KVM_VM_DATA_BASE (KVM_VMM_BASE + KVM_VMM_SIZE)
+
+
+#define KVM_P2M_BASE    KVM_VM_DATA_BASE
+#define KVM_P2M_OFS     0
+#define KVM_P2M_SIZE    (8UL << 20)
+
+#define KVM_VHPT_BASE   (KVM_P2M_BASE + KVM_P2M_SIZE)
+#define KVM_VHPT_OFS    KVM_P2M_SIZE
+#define KVM_VHPT_BLOCK_SIZE   (2UL << 20)
+#define VHPT_SHIFT      20
+#define VHPT_SIZE       (1UL << VHPT_SHIFT)
+#define VHPT_NUM_ENTRIES (1<<(VHPT_SHIFT-5))
+
+#define KVM_VTLB_BASE   (KVM_VHPT_BASE+KVM_VHPT_BLOCK_SIZE)
+#define KVM_VTLB_OFS    (KVM_VHPT_OFS+KVM_VHPT_BLOCK_SIZE)
+#define KVM_VTLB_BLOCK_SIZE   (1UL<<20)
+#define VTLB_SHIFT      20
+#define VTLB_SIZE       (1UL<<VTLB_SHIFT)
+#define VTLB_NUM_ENTRIES (1<<(VTLB_SHIFT-5))
+
+#define KVM_VPD_BASE   (KVM_VTLB_BASE+KVM_VTLB_BLOCK_SIZE)
+#define KVM_VPD_OFS    (KVM_VTLB_OFS+KVM_VTLB_BLOCK_SIZE)
+#define KVM_VPD_BLOCK_SIZE   (2UL<<20)
+#define VPD_SHIFT       16
+#define VPD_SIZE        (1UL<<VPD_SHIFT)
+
+#define KVM_VCPU_BASE   (KVM_VPD_BASE+KVM_VPD_BLOCK_SIZE)
+#define KVM_VCPU_OFS    (KVM_VPD_OFS+KVM_VPD_BLOCK_SIZE)
+#define KVM_VCPU_BLOCK_SIZE   (2UL<<20)
+#define VCPU_SHIFT 16
+#define VCPU_SIZE (1UL<<VCPU_SHIFT)
+#define MAX_VCPU_NUM KVM_VCPU_BLOCK_SIZE/VCPU_SIZE
+
+#define KVM_VM_BASE     (KVM_VCPU_BASE+KVM_VCPU_BLOCK_SIZE)
+#define KVM_VM_OFS      (KVM_VCPU_OFS+KVM_VCPU_BLOCK_SIZE)
+#define KVM_VM_BLOCK_SIZE     (1UL<<20)
+
+/* Get vpd, vhpt, tlb, vcpu, base*/
+#define VPD_ADDR(n) (KVM_VPD_BASE+n*VPD_SIZE)
+#define VHPT_ADDR(n) (KVM_VHPT_BASE+n*VHPT_SIZE)
+#define VTLB_ADDR(n) (KVM_VTLB_BASE+n*VTLB_SIZE)
+#define VCPU_ADDR(n) (KVM_VCPU_BASE+n*VCPU_SIZE)
+
+/*IO section definitions*/
+#define IOREQ_READ      1
+#define IOREQ_WRITE     0
+
+#define STATE_IOREQ_NONE        0
+#define STATE_IOREQ_READY       1
+#define STATE_IOREQ_INPROCESS   2
+#define STATE_IORESP_READY      3
+
+/*Guest Physical address layout.*/
+#define GPFN_MEM        (0UL << 60) /* Guest pfn is normal mem */
+#define GPFN_FRAME_BUFFER   (1UL << 60) /* VGA framebuffer */
+#define GPFN_LOW_MMIO       (2UL << 60) /* Low MMIO range */
+#define GPFN_PIB        (3UL << 60) /* PIB base */
+#define GPFN_IOSAPIC        (4UL << 60) /* IOSAPIC base */
+#define GPFN_LEGACY_IO      (5UL << 60) /* Legacy I/O base */
+#define GPFN_GFW        (6UL << 60) /* Guest Firmware */
+#define GPFN_HIGH_MMIO      (7UL << 60) /* High MMIO range */
+
+#define GPFN_IO_MASK        (7UL << 60) /* Guest pfn is I/O type */
+#define GPFN_INV_MASK       (1UL << 63) /* Guest pfn is invalid */
+#define INVALID_MFN       (~0UL)
+#define MEM_G   (1UL << 30)
+#define MEM_M   (1UL << 20)
+#define MMIO_START       (3 * MEM_G)
+#define MMIO_SIZE        (512 * MEM_M)
+#define VGA_IO_START     0xA0000UL
+#define VGA_IO_SIZE      0x20000
+#define LEGACY_IO_START  (MMIO_START + MMIO_SIZE)
+#define LEGACY_IO_SIZE   (64*MEM_M)
+#define IO_SAPIC_START   0xfec00000UL
+#define IO_SAPIC_SIZE    0x100000
+#define PIB_START 0xfee00000UL
+#define PIB_SIZE 0x200000
+#define GFW_START        (4*MEM_G-16*MEM_M)
+#define GFW_SIZE         (16*MEM_M)
+
+/*Deliver mode, defined for ioapic.c*/
+#define dest_Fixed IOSAPIC_FIXED
+#define dest_LowestPrio IOSAPIC_LOWEST_PRIORITY
+
+#define NMI_VECTOR      		2
+#define ExtINT_VECTOR       		0
+#define NULL_VECTOR     		-1
+#define IA64_SPURIOUS_INT_VECTOR    	0x0f
+
+#define VCPU_LID(v) (((u64)(v)->vcpu_id)<<24)
+
+/*
+ *Delivery mode
+ */
+#define SAPIC_DELIV_SHIFT      8
+#define SAPIC_FIXED            0x0
+#define SAPIC_LOWEST_PRIORITY  0x1
+#define SAPIC_PMI              0x2
+#define SAPIC_NMI              0x4
+#define SAPIC_INIT             0x5
+#define SAPIC_EXTINT           0x7
+
+struct kvm;
+struct kvm_vcpu;
+
+struct kvm_ioreq {
+	uint64_t addr;          /*  physical address		*/
+	uint64_t size;          /*  size in bytes		*/
+	uint64_t data;          /*  data (or paddr of data)     */
+	uint8_t state:4;
+	uint8_t dir:1;          /*  1=read, 0=write             */
+};
+typedef struct kvm_ioreq ioreq_t;
+
+/*Pal data struct */
+typedef struct pal_call{
+	/*In area*/
+	uint64_t gr28;
+	uint64_t gr29;
+	uint64_t gr30;
+	uint64_t gr31;
+	/*Out area*/
+	struct ia64_pal_retval ret;
+} pal_call_t;
+
+/* Sal data structure */
+typedef struct sal_call{
+	/*In area*/
+	uint64_t in0;
+	uint64_t in1;
+	uint64_t in2;
+	uint64_t in3;
+	uint64_t in4;
+	uint64_t in5;
+	uint64_t in6;
+	uint64_t in7;
+	/*Our area*/
+	struct sal_ret_values ret;
+} sal_call_t;
+
+/*Guest change rr6*/
+typedef struct switch_rr6 {
+	uint64_t old_rr;
+	uint64_t new_rr;
+} switch_rr6_t;
+
+typedef union{
+	unsigned long val;
+	struct {
+		unsigned long rv  : 3;
+		unsigned long ir  : 1;
+		unsigned long eid : 8;
+		unsigned long id  : 8;
+		unsigned long ib_base : 44;
+	};
+} ia64_ipi_a;
+
+typedef union{
+	unsigned long val;
+	struct {
+		unsigned long vector : 8;
+		unsigned long dm  : 3;
+		unsigned long ig  : 53;
+	};
+} ia64_ipi_d;
+
+/*ipi check exit data*/
+typedef struct ipi_data{
+	ia64_ipi_a addr;
+	ia64_ipi_d data;
+} ipi_data_t;
+
+/*Exit control data */
+struct exit_ctl_data{
+	uint32_t exit_reason;
+	uint32_t vm_status;
+	union {
+		ioreq_t		ioreq;
+		pal_call_t	pal_data;
+		sal_call_t	sal_data;
+		switch_rr6_t	rr_data;
+		ipi_data_t	ipi_data;
+	} u;
+};
+
+union pte_flags {
+	struct {
+		unsigned long p    :  1; /*0      */
+		unsigned long      :  1; /* 1     */
+		unsigned long ma   :  3; /* 2-4   */
+		unsigned long a    :  1; /* 5     */
+		unsigned long d    :  1; /* 6     */
+		unsigned long pl   :  2; /* 7-8   */
+		unsigned long ar   :  3; /* 9-11  */
+		unsigned long ppn  : 38; /* 12-49 */
+		unsigned long      :  2; /* 50-51 */
+		unsigned long ed   :  1; /* 52    */
+	};
+	unsigned long val;
+};
+
+
+typedef struct thash_data {
+	union {
+		struct {
+			unsigned long p    :  1; /* 0 */
+			unsigned long rv1  :  1; /* 1 */
+			unsigned long ma   :  3; /* 2-4 */
+			unsigned long a    :  1; /* 5 */
+			unsigned long d    :  1; /* 6 */
+			unsigned long pl   :  2; /* 7-8 */
+			unsigned long ar   :  3; /* 9-11 */
+			unsigned long ppn  : 38; /* 12-49 */
+			unsigned long rv2  :  2; /* 50-51 */
+			unsigned long ed   :  1; /* 52 */
+			unsigned long ig1  : 11; /* 53-63 */
+		};
+		struct {
+			unsigned long __rv1 : 53;     /* 0-52 */
+			unsigned long contiguous : 1; /*53 */
+			unsigned long tc : 1;         /* 54 TR or TC */
+			unsigned long cl : 1;
+			/* 55 I side or D side cache line */
+			unsigned long len  :  4;      /* 56-59 */
+			unsigned long io  : 1;	/* 60 entry is for io or not */
+			unsigned long nomap : 1;
+			/* 61 entry cann't be inserted into machine TLB.*/
+			unsigned long checked : 1;
+			/* 62 for VTLB/VHPT sanity check */
+			unsigned long invalid : 1;
+			/* 63 invalid entry */
+		};
+		unsigned long page_flags;
+	};                  /* same for VHPT and TLB */
+
+	union {
+		struct {
+			unsigned long rv3  :  2;
+			unsigned long ps   :  6;
+			unsigned long key  : 24;
+			unsigned long rv4  : 32;
+		};
+		unsigned long itir;
+	};
+	union {
+		struct {
+			unsigned long ig2  :  12;
+			unsigned long vpn  :  49;
+			unsigned long vrn  :   3;
+		};
+		unsigned long ifa;
+		unsigned long vadr;
+		struct {
+			unsigned long tag  :  63;
+			unsigned long ti   :  1;
+		};
+		unsigned long etag;
+	};
+	union {
+		struct thash_data *next;
+		unsigned long rid;
+		unsigned long gpaddr;
+	};
+} thash_data_t;
+
+typedef union {
+	unsigned long val;
+	struct {
+		unsigned long ve : 1;
+		unsigned long reserved0 : 1;
+		unsigned long size : 6;
+		unsigned long vf : 1;
+		unsigned long reserved1 : 6;
+		unsigned long base : 49;
+	};
+} ia64_pta;
+
+typedef struct thash_cb {
+	/* THASH base information */
+	thash_data_t  *hash; /* hash table pointer, aligned at thash_sz.*/
+	ia64_pta      pta;
+	int           num;
+} thash_cb_t;
+
+typedef union context {
+	/* 8K size */
+	unsigned long       dummy[1024];
+	struct {
+		unsigned long       psr;
+		unsigned long       pr;
+		unsigned long       caller_unat;
+		unsigned long       pad;
+		unsigned long       gr[32];
+		unsigned long       ar[128];
+		unsigned long       br[8];
+		unsigned long       cr[128];
+		unsigned long       rr[8];
+		unsigned long       ibr[8];
+		unsigned long       dbr[8];
+		unsigned long       pkr[8];
+		struct ia64_fpreg   fr[128];
+	};
+} context_t;
+
+#define	NITRS	8
+#define NDTRS	8
+
+struct kvm_vcpu_stat {
+};
+struct kvm_vcpu_arch {
+	int launched;
+#define VCPU_MP_STATE_RUNNABLE          0
+#define VCPU_MP_STATE_UNINITIALIZED     1
+#define VCPU_MP_STATE_INIT_RECEIVED     2
+#define VCPU_MP_STATE_SIPI_RECEIVED     3
+#define VCPU_MP_STATE_HALTED            4
+	int mp_state;
+	void *pio_data;
+	struct kvm_lapic *apic;    /* kernel irqchip context */
+	struct kvm_pio_request pio;
+	int sipi_vector;
+	/* Save the state of vcpu.
+	   This is the first entry to speed up accesses.  */
+
+	struct exit_ctl_data exit_data;
+	struct vpd *vpd;
+	unsigned long vmm_rr;
+	unsigned long host_rr6;
+	unsigned long psbits[8];
+	unsigned long cr_iipa;
+	unsigned long cr_isr;
+	unsigned long vsa_base;
+	unsigned long __gp;
+	/* TR and TC.  */
+	thash_data_t itrs[NITRS];
+	thash_data_t dtrs[NDTRS];
+	/* Bit is set if there is a tr/tc for the region.  */
+	unsigned char itr_regions;
+	unsigned char dtr_regions;
+	unsigned char tc_regions;
+	/* purge all */
+	unsigned long ptce_base;
+	unsigned long ptce_count[2];
+	unsigned long ptce_stride[2];
+	/* itc/itm */
+	unsigned long last_itc;
+	unsigned long itc_offset;
+	unsigned long itc_check;
+	unsigned long timer_check;
+	unsigned long timer_pending;
+
+
+	unsigned long vrr[8];
+	unsigned long ibr[8];
+	unsigned long dbr[8];
+	unsigned long irr[4];	    /* Interrupt request register.  */
+	unsigned long insvc[4];		/* Interrupt in service.  */
+	unsigned long xtp;
+
+	/* These fields are copied from arch_domain to make access
+	easier/faster in assembly code.  */
+	unsigned long metaphysical_rr0; /* from kvm_arch (so is pinned) */
+	unsigned long metaphysical_rr4;	/* from kvm_arch (so is pinned) */
+	unsigned long metaphysical_saved_rr0; /* from kvm_arch          */
+	unsigned long metaphysical_saved_rr4; /* from kvm_arch          */
+	unsigned long fp_psr;       /*used for lazy float register */
+	unsigned long saved_gp;
+	int breakimm;			/*from arch_domain (so is pinned) */
+	int starting_rid;		/*first RID assigned to domain */
+	int ending_rid;		/* one beyond highest RID assigned to domain */
+	thash_cb_t vtlb;
+	thash_cb_t vhpt;
+	char irq_check;
+	char irq_new_pending;
+
+	/*for phycial  emulation */
+	int mode_flags;
+	int last_run_cpu;
+	unsigned long opcode;
+	unsigned long cause;
+	context_t host;
+	context_t guest;
+
+};
+
+struct kvm_vm_stat {
+	u64 remote_tlb_flush;
+};
+
+struct kvm_arch {
+	unsigned long	vm_base;
+	unsigned long	metaphysical_rr0;
+	unsigned long	metaphysical_rr4;
+	unsigned long	vmm_init_rr;
+	unsigned long	vhpt_base;
+	unsigned long	vtlb_base;
+	unsigned long 	vpd_base;
+	struct kvm_ioapic *vioapic;
+	struct kvm_vm_stat stat;
+};
+
+typedef union {
+	u64 value;
+	struct {
+		u64 number : 8;
+		u64 revision : 8;
+		u64 model : 8;
+		u64 family : 8;
+		u64 archrev : 8;
+		u64 rv : 24;
+	};
+} cpuid3_t;
+
+typedef int kvm_vmm_entry(void);
+typedef void kvm_tramp_entry(context_t *host, context_t *guest);
+
+struct kvm_vmm_info{
+	struct module	*module;
+	kvm_vmm_entry 	*vmm_entry;
+	kvm_tramp_entry *tramp_entry;
+	unsigned long 	vmm_ivt;
+};
+
+int kvm_highest_pending_irq(struct kvm_vcpu *vcpu);
+int kvm_emulate_halt(struct kvm_vcpu *vcpu);
+
+#define smp_call_function_mask(cpus_mask, func, info, wait)\
+	smp_call_function(func, info, 0, wait)
+
+#endif
diff --git a/include/asm-ia64/kvm_para.h b/include/asm-ia64/kvm_para.h
new file mode 100644
index 0000000..52ce02d
--- /dev/null
+++ b/include/asm-ia64/kvm_para.h
@@ -0,0 +1,9 @@
+#ifndef __IA64_KVM_PARA_H
+#define __IA64_KVM_PARA_H
+
+static inline unsigned int kvm_arch_para_features(void)
+{
+	return 0;
+}
+
+#endif
-- 
1.5.2


[-- Attachment #3: 0002-kvm-ia64-Add-kvm_ia64.c.patch --]
[-- Type: application/octet-stream, Size: 37398 bytes --]

From 2193934a070c8d44b9502b759b187bc5e8d7cb7d Mon Sep 17 00:00:00 2001
From: Zhang Xiantao <xiantao.zhang@intel.com>
Date: Wed, 19 Dec 2007 14:08:44 +0800
Subject: [PATCH] kvm/ia64: Add kvm_ia64.c

This patch adds kvm_ia64.c, which is the main body of kvm module, and is
ia64-specific part for kvm module.
Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com>
---
 arch/ia64/kvm/kvm_ia64.c | 1586 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1586 insertions(+), 0 deletions(-)
 create mode 100644 arch/ia64/kvm/kvm_ia64.c

diff --git a/arch/ia64/kvm/kvm_ia64.c b/arch/ia64/kvm/kvm_ia64.c
new file mode 100644
index 0000000..60b325e
--- /dev/null
+++ b/arch/ia64/kvm/kvm_ia64.c
@@ -0,0 +1,1585 @@
+/*
+ * kvm_ia64.c: Basic KVM suppport On Itanium series processors
+ *
+ *
+ * 	Copyright (C) 2007, Intel Corporation.
+ *  	Xiantao Zhang  (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/errno.h>
+#include <linux/percpu.h>
+#include <linux/gfp.h>
+#include <linux/fs.h>
+#include <linux/smp.h>
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+#include <linux/bitops.h>
+
+#include <asm/pgtable.h>
+#include <asm/gcc_intrin.h>
+#include <asm/pal.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+
+#include "ia64_regs.h"
+#include "misc.h"
+#include "vti.h"
+#include "iodev.h"
+#include "ioapic.h"
+#include "lapic.h"
+
+static unsigned long kvm_vmm_base;
+static unsigned long kvm_vsa_base;
+static unsigned long kvm_vm_buffer;
+static unsigned long kvm_vm_buffer_size;
+unsigned long kvm_vmm_gp;
+
+static long vp_env_info;
+
+static struct kvm_vmm_info *kvm_vmm_info;
+
+static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu);
+
+typedef void (*__insert_tr)(uint64_t slot, uint64_t va, uint64_t pa,
+				uint64_t log);
+__insert_tr kvm_insert_idtr;
+
+extern void __kvm_insert_idtr(uint64_t slot, uint64_t va, uint64_t pa,
+			uint64_t log);
+extern void __kvm_purge_idtr(uint64_t va, uint64_t log);
+
+struct kvm_stats_debugfs_item debugfs_entries[] = {
+};
+
+
+struct fdesc{
+    unsigned long ip;
+    unsigned long gp;
+};
+
+static void kvm_flush_icache(unsigned long start, unsigned long len)
+{
+	int l;
+
+	for (l = 0; l < (len + 32); l += 32)
+		ia64_fc(start + l);
+
+	ia64_sync_i();
+	ia64_srlz_i();
+}
+
+/*
+ *FIXME:This is a dirty hack, since tr insertion code
+ *should be mapped by tr in virtual mode. Once kernel
+ * provides kernel TR insertion interface, we can remove
+ *it.
+ */
+
+#define HACK_TR_INSERT_ADDR_START 0xa000000100007000UL
+struct fdesc fdesc_itr_entry;
+
+
+void kvm_hack_insert_tr(void)
+{
+	unsigned long src_addr;
+	src_addr = *(unsigned long *)__kvm_insert_idtr;
+	memcpy((void *)HACK_TR_INSERT_ADDR_START, (void *)src_addr, 0x100);
+
+	fdesc_itr_entry.ip = HACK_TR_INSERT_ADDR_START;
+	kvm_insert_idtr = (__insert_tr)&fdesc_itr_entry;
+
+	kvm_flush_icache(HACK_TR_INSERT_ADDR_START, 0x100) ;
+
+}
+
+static void kvm_flush_tlb_all(void)
+{
+	unsigned long i, j, count0, count1, stride0, stride1, addr;
+
+	addr    = local_cpu_data->ptce_base;
+	count0  = local_cpu_data->ptce_count[0];
+	count1  = local_cpu_data->ptce_count[1];
+	stride0 = local_cpu_data->ptce_stride[0];
+	stride1 = local_cpu_data->ptce_stride[1];
+
+	for (i = 0; i < count0; ++i) {
+		for (j = 0; j < count1; ++j) {
+			ia64_ptce(addr);
+			addr += stride1;
+		}
+		addr += stride0;
+	}
+	ia64_srlz_i();			/* srlz.i implies srlz.d */
+}
+
+long ia64_pal_vp_create(u64 *vpd, u64 *host_iva, u64 *opt_handler)
+{
+	struct ia64_pal_retval iprv;
+
+	PAL_CALL_STK(iprv, PAL_VP_CREATE, (u64)vpd, (u64)host_iva,
+			(u64)opt_handler);
+
+	return iprv.status;
+}
+
+static  DEFINE_SPINLOCK(vp_lock);
+
+void kvm_arch_hardware_enable(void *garbage)
+{
+	long  status;
+	long  tmp_base;
+	unsigned long pte;
+	unsigned long saved_psr;
+
+	pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base),
+				PAGE_KERNEL));
+	local_irq_save(saved_psr);
+	kvm_insert_idtr(IA64_TR_VMM, KVM_VMM_BASE,
+			pte, KVM_VMM_SHIFT);
+	local_irq_restore(saved_psr);
+
+	spin_lock(&vp_lock);
+	status = ia64_pal_vp_init_env(kvm_vsa_base ?
+				VP_INIT_ENV : VP_INIT_ENV_INITALIZE,
+			__pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base);
+	if (status != 0) {
+		printk(KERN_WARNING"kvm:Failed to Enable VT Support!!!!\n");
+		return ;
+	}
+
+	if (!kvm_vsa_base) {
+		kvm_vsa_base = tmp_base;
+		printk(KERN_INFO"kvm:kvm_vsa_base:0x%lx\n", kvm_vsa_base);
+	}
+	spin_unlock(&vp_lock);
+	__kvm_purge_idtr(KVM_VMM_BASE, KVM_VMM_SHIFT);
+}
+
+void kvm_arch_hardware_disable(void *garbage)
+{
+
+	long status;
+	unsigned long pte;
+	unsigned long saved_psr;
+	unsigned long host_iva = ia64_getreg(_IA64_REG_CR_IVA);
+
+	pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base),
+				PAGE_KERNEL));
+
+	local_irq_save(saved_psr);
+	kvm_insert_idtr(IA64_TR_VMM, KVM_VMM_BASE,
+			pte, KVM_VMM_SHIFT);
+	local_irq_restore(saved_psr);
+
+	status = ia64_pal_vp_exit_env(host_iva);
+	if (status)
+		printk(KERN_DEBUG"kvm: Failed to disable VT support! :%ld\n",
+				status);
+	__kvm_purge_idtr(KVM_VMM_BASE, KVM_VMM_SHIFT);
+}
+
+void kvm_arch_check_processor_compat(void *rtn)
+{
+	*(int *)rtn = 0;
+}
+
+int kvm_dev_ioctl_check_extension(long ext)
+{
+
+	int r;
+
+	switch (ext) {
+	case KVM_CAP_IRQCHIP:
+	case KVM_CAP_USER_MEMORY:
+
+		r = 1;
+		break;
+	default:
+		r = 0;
+	}
+	return r;
+
+}
+
+static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
+					gpa_t addr)
+{
+	struct kvm_io_device *dev;
+
+	dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr);
+
+	return dev;
+}
+
+static int handle_vm_error(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+	kvm_run->hw.hardware_exit_reason = 1;
+	return 0;
+}
+
+static int handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	ioreq_t *p;
+	struct kvm_io_device *mmio_dev;
+
+	p = kvm_get_vcpu_ioreq(vcpu);
+
+	if ((p->addr & PAGE_MASK) == IOAPIC_DEFAULT_BASE_ADDRESS)
+		goto mmio;
+	vcpu->mmio_needed = 1;
+	vcpu->mmio_phys_addr = kvm_run->mmio.phys_addr = p->addr;
+	vcpu->mmio_size = kvm_run->mmio.len = p->size;
+	vcpu->mmio_is_write = kvm_run->mmio.is_write = !p->dir;
+
+	if (vcpu->mmio_is_write)
+		memcpy(vcpu->mmio_data, &p->data, p->size);
+	memcpy(kvm_run->mmio.data, &p->data, p->size);
+	kvm_run->exit_reason = KVM_EXIT_MMIO;
+	return 0;
+mmio:
+	mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr);
+	if (mmio_dev) {
+		if (!p->dir)
+			kvm_iodevice_write(mmio_dev, p->addr, p->size,
+						&p->data);
+		else
+			kvm_iodevice_read(mmio_dev, p->addr, p->size,
+						&p->data);
+
+	} else
+		printk(KERN_ERR"kvm: No iodevice found !\n");
+	p->state = STATE_IORESP_READY;
+
+	return 1;
+}
+
+static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu,
+		gpa_t addr)
+{
+	return kvm_io_bus_find_dev(&vcpu->kvm->pio_bus, addr);
+}
+
+static void kernel_pio(struct kvm_io_device *pio_dev,
+		struct kvm_vcpu *vcpu,
+		void *pd)
+{
+
+	mutex_lock(&vcpu->kvm->lock);
+	if (vcpu->arch.pio.in)
+		kvm_iodevice_read(pio_dev, vcpu->arch.pio.port,
+				vcpu->arch.pio.size,
+				pd);
+	else
+		kvm_iodevice_write(pio_dev, vcpu->arch.pio.port,
+				vcpu->arch.pio.size,
+				pd);
+	mutex_unlock(&vcpu->kvm->lock);
+}
+
+int complete_pio(struct kvm_vcpu *vcpu)
+{
+	struct kvm_pio_request *io = &vcpu->arch.pio;
+	ioreq_t *p = kvm_get_vcpu_ioreq(vcpu);
+
+	if (io->in)
+		memcpy(&p->data, vcpu->arch.pio_data,
+				io->size);
+	p->state = STATE_IORESP_READY;
+	io->count -= io->cur_count;
+	io->cur_count = 0;
+
+	return 0;
+}
+
+static int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
+		int size, unsigned port)
+{
+	struct kvm_io_device *pio_dev;
+
+	vcpu->run->exit_reason = KVM_EXIT_IO;
+	vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
+	vcpu->run->io.size = vcpu->arch.pio.size = size;
+	vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE;
+	vcpu->run->io.count = vcpu->arch.pio.count =
+					vcpu->arch.pio.cur_count = 1;
+	vcpu->run->io.port = vcpu->arch.pio.port = port;
+	vcpu->arch.pio.in = in;
+	vcpu->arch.pio.string = 0;
+	vcpu->arch.pio.down = 0;
+	vcpu->arch.pio.guest_page_offset = 0;
+	vcpu->arch.pio.rep = 0;
+
+	memcpy(vcpu->arch.pio_data, &kvm_get_vcpu_ioreq(vcpu)->data, size);
+
+	pio_dev = vcpu_find_pio_dev(vcpu, port);
+	if (pio_dev) {
+		kernel_pio(pio_dev, vcpu, vcpu->arch.pio_data);
+		complete_pio(vcpu);
+		return 1;
+	}
+	return 0;
+}
+
+static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	ioreq_t *p = kvm_get_vcpu_ioreq(vcpu);
+
+	return kvm_emulate_pio(vcpu, kvm_run, p->dir, p->size, p->addr);
+}
+
+extern int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
+static int handle_pal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	struct exit_ctl_data *p;
+
+	p = kvm_get_exit_data(vcpu);
+
+	if (p->exit_reason == EXIT_REASON_PAL_CALL)
+		return kvm_pal_emul(vcpu, kvm_run);
+	else {
+		kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+		kvm_run->hw.hardware_exit_reason = 2;
+		return 0;
+	}
+}
+
+extern void kvm_sal_emul(struct kvm_vcpu *vcpu);
+static int handle_sal_call(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	struct exit_ctl_data *p;
+
+	p = kvm_get_exit_data(vcpu);
+
+	if (p->exit_reason == EXIT_REASON_SAL_CALL) {
+		kvm_sal_emul(vcpu);
+		return 1;
+	} else {
+		kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+		kvm_run->hw.hardware_exit_reason = 3;
+		return 0;
+	}
+
+}
+
+/*
+ *  offset: address offset to IPI space.
+ *  value:  deliver value.
+ */
+static void vcpu_deliver_ipi(struct kvm_vcpu *vcpu, uint64_t dm,
+				uint64_t vector)
+{
+	switch (dm) {
+	case SAPIC_FIXED:
+		kvm_apic_set_irq(vcpu, vector, 0);
+		break;
+	case SAPIC_NMI:
+		kvm_apic_set_irq(vcpu, 2, 0);
+		break;
+	case SAPIC_EXTINT:
+		kvm_apic_set_irq(vcpu, 0, 0);
+		break;
+	case SAPIC_INIT:
+	case SAPIC_PMI:
+	default:
+		printk(KERN_ERR"kvm:Unimplemented Deliver reserved IPI!\n");
+		break;
+	}
+}
+
+static struct kvm_vcpu *lid_to_vcpu(struct kvm *kvm, unsigned long id,
+			unsigned long eid)
+{
+	ia64_lid_t lid;
+	int i;
+
+	for (i = 0; i < KVM_MAX_VCPUS; i++) {
+		if (kvm->vcpus[i]) {
+			lid.val = VCPU_LID(kvm->vcpus[i]);
+			if (lid.id == id && lid.eid == eid)
+				return kvm->vcpus[i];
+		}
+	}
+
+	return NULL;
+}
+
+static int handle_ipi(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	struct exit_ctl_data *p = kvm_get_exit_data(vcpu);
+	struct kvm_vcpu *target_vcpu;
+	ia64_ipi_a addr = p->u.ipi_data.addr;
+	ia64_ipi_d data = p->u.ipi_data.data;
+
+	target_vcpu = lid_to_vcpu(vcpu->kvm, addr.id, addr.eid);
+	if (!target_vcpu)
+		return handle_vm_error(vcpu, kvm_run);
+
+	if (!target_vcpu->arch.launched) {
+		printk(KERN_ERR"kvm: Need to implement for smp!\n");
+		return handle_vm_error(vcpu, kvm_run);
+	} else {
+		vcpu_deliver_ipi(target_vcpu, data.dm, data.vector);
+		if (target_vcpu != vcpu)
+			kvm_vcpu_kick(target_vcpu);
+	}
+
+	return 1;
+}
+
+static int handle_switch_rr6(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	return 1;
+}
+
+int kvm_emulate_halt(struct kvm_vcpu *vcpu)
+{
+	if (irqchip_in_kernel(vcpu->kvm)) {
+		vcpu->arch.mp_state = VCPU_MP_STATE_HALTED;
+		kvm_vcpu_block(vcpu);
+		if (vcpu->arch.mp_state != VCPU_MP_STATE_RUNNABLE)
+			return -EINTR;
+		return 1;
+	} else {
+		printk(KERN_ERR"kvm: Unsupported userspace halt!");
+		return 0;
+	}
+
+}
+
+static int handle_vm_shutdown(struct kvm_vcpu *vcpu,
+		struct kvm_run *kvm_run)
+{
+	kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+	return 0;
+}
+
+static int handle_external_interrupt(struct kvm_vcpu *vcpu,
+		struct kvm_run *kvm_run)
+{
+	return 1;
+}
+
+static int (*kvm_vti_exit_handlers[])(struct kvm_vcpu *vcpu,
+		struct kvm_run *kvm_run) = {
+	[EXIT_REASON_VM_PANIC]              = handle_vm_error,
+	[EXIT_REASON_IO_INSTRUCTION]        = handle_io,
+	[EXIT_REASON_MMIO_INSTRUCTION]      = handle_mmio,
+	[EXIT_REASON_PAL_CALL]              = handle_pal_call,
+	[EXIT_REASON_SAL_CALL]              = handle_sal_call,
+	[EXIT_REASON_SWITCH_RR6]            = handle_switch_rr6,
+	[EXIT_REASON_VM_DESTROY]            = handle_vm_shutdown,
+	[EXIT_REASON_EXTERNAL_INTERRUPT]    = handle_external_interrupt,
+	[EXIT_REASON_IPI]		    = handle_ipi,
+
+};
+
+static const int kvm_vti_max_exit_handlers =
+		sizeof(kvm_vti_exit_handlers)/sizeof(*kvm_vti_exit_handlers);
+
+static void kvm_prepare_guest_switch(struct kvm_vcpu *vcpu)
+{
+}
+
+static uint32_t kvm_get_exit_reason(struct kvm_vcpu *vcpu)
+{
+	struct exit_ctl_data *p_exit_data;
+
+	p_exit_data = kvm_get_exit_data(vcpu);
+	return p_exit_data->exit_reason;
+
+}
+
+/*
+ * The guest has exited.  See if we can fix it or if we need userspace
+ * assistance.
+ */
+static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
+{
+	u32 exit_reason = kvm_get_exit_reason(vcpu);
+
+	if (exit_reason < kvm_vti_max_exit_handlers
+			&& kvm_vti_exit_handlers[exit_reason])
+		return kvm_vti_exit_handlers[exit_reason](vcpu, kvm_run);
+	else {
+		kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
+		kvm_run->hw.hardware_exit_reason = exit_reason;
+	}
+	return 0;
+}
+
+static inline void vti_set_rr6(unsigned long rr6)
+{
+	ia64_set_rr(RR6, rr6);
+	ia64_srlz_i();
+}
+
+/*Ensure no TR entries in slot 6 and slot 7 before getting called.*/
+static void kvm_insert_vmm_mapping(struct kvm_vcpu *vcpu)
+{
+	unsigned long pte;
+	struct kvm *kvm = vcpu->kvm;
+
+	/*Insert a pair of tr to map vmm*/
+	pte = pte_val(mk_pte_phys(__pa(kvm_vmm_base), PAGE_KERNEL));
+	kvm_insert_idtr(IA64_TR_VMM, KVM_VMM_BASE, pte, KVM_VMM_SHIFT);
+
+	/*Insert a pairt of tr to map data of vm*/
+	pte = pte_val(mk_pte_phys(__pa(kvm->arch.vm_base), PAGE_KERNEL));
+	kvm_insert_idtr(IA64_TR_VM_DATA, KVM_VM_DATA_BASE,
+					pte, KVM_VM_DATA_SHIFT);
+
+}
+
+static void kvm_purge_vmm_mapping(void)
+{
+
+	unsigned long ps;
+
+	/*Purge itr and dtr in slot 6.*/
+	ps = KVM_VMM_SHIFT;
+	__kvm_purge_idtr(KVM_VMM_BASE, ps);
+
+	/*Purge itr and dtr in slot 7.*/
+	ps = KVM_VM_DATA_SHIFT;
+	__kvm_purge_idtr(KVM_VM_DATA_BASE, ps);
+
+}
+
+static void kvm_vcpu_pre_transition(struct kvm_vcpu *vcpu)
+{
+	int cpu = smp_processor_id();
+
+	if (vcpu->arch.last_run_cpu != cpu ||
+			per_cpu(last_vcpu, cpu) != vcpu) {
+		per_cpu(last_vcpu, cpu) = vcpu;
+		vcpu->arch.last_run_cpu = cpu;
+		kvm_flush_tlb_all();
+	}
+
+	vcpu->arch.host_rr6 = ia64_get_rr(RR6);
+	vti_set_rr6(vcpu->arch.vmm_rr);
+	kvm_insert_vmm_mapping(vcpu);
+}
+static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu)
+{
+	kvm_purge_vmm_mapping();
+	vti_set_rr6(vcpu->arch.host_rr6);
+}
+
+static void vti_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	context_t *host_ctx, *guest_ctx;
+
+	/*Get host and guest context with guest address space.*/
+
+	host_ctx = kvm_get_host_context(vcpu);
+	guest_ctx = kvm_get_guest_context(vcpu);
+
+	kvm_vcpu_pre_transition(vcpu);
+	kvm_vmm_info->tramp_entry(host_ctx, guest_ctx);
+	kvm_vcpu_post_transition(vcpu);
+}
+
+static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	int r;
+
+again:
+	preempt_disable();
+
+	kvm_prepare_guest_switch(vcpu);
+	local_irq_disable();
+
+	if (signal_pending(current)) {
+		local_irq_enable();
+		preempt_enable();
+		r = -EINTR;
+		kvm_run->exit_reason = KVM_EXIT_INTR;
+		goto out;
+	}
+
+	/*FIXME::need to inject interrupts here for ia64?*/
+	vcpu->guest_mode = 1;
+	kvm_guest_enter();
+
+	vti_vcpu_run(vcpu, kvm_run);
+
+	vcpu->arch.launched = 1;
+	vcpu->guest_mode = 0;
+	local_irq_enable();
+
+	/*
+	 * We must have an instruction between local_irq_enable() and
+	 * kvm_guest_exit(), so the timer interrupt isn't delayed by
+	 * the interrupt shadow.  The stat.exits increment will do nicely.
+	 * But we need to prevent reordering, hence this barrier():
+	 */
+	barrier();
+
+	kvm_guest_exit();
+
+	preempt_enable();
+
+	r = kvm_handle_exit(kvm_run, vcpu);
+
+	if (r > 0) {
+		if (0) {
+			/*FIXME: Handle irq injection.... */
+			r = -EINTR;
+			kvm_run->exit_reason = KVM_EXIT_INTR;
+			goto out;
+		}
+		if (!need_resched())
+			goto again;
+	}
+
+out:
+	if (r > 0) {
+		kvm_resched(vcpu);
+		goto again;
+	}
+
+	return r;
+}
+
+static void kvm_set_mmio_data(struct kvm_vcpu *vcpu)
+{
+	ioreq_t *p = kvm_get_vcpu_ioreq(vcpu);
+	if (!vcpu->mmio_is_write)
+		memcpy(&p->data, vcpu->mmio_data, 8);
+	p->state = STATE_IORESP_READY;
+}
+
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	int r;
+	sigset_t sigsaved;
+
+	vcpu_load(vcpu);
+
+	if (unlikely(vcpu->arch.mp_state == VCPU_MP_STATE_UNINITIALIZED)) {
+		kvm_vcpu_block(vcpu);
+		vcpu_put(vcpu);
+		return -EAGAIN;
+	}
+
+	if (vcpu->sigset_active)
+		sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
+
+	if (vcpu->arch.pio.cur_count) {
+		r = complete_pio(vcpu);
+		if (r)
+			goto out;
+	}
+
+	if (vcpu->mmio_needed) {
+		memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);
+		kvm_set_mmio_data(vcpu);
+		vcpu->mmio_read_completed = 1;
+		vcpu->mmio_needed = 0;
+	}
+	r = __vcpu_run(vcpu, kvm_run);
+
+out:
+	if (vcpu->sigset_active)
+		sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+	vcpu_put(vcpu);
+	return r;
+}
+
+/*
+ * Allocate 16M memory for every vm to hold its specific data.
+ * Its memory map is defined in kvm_host.h.
+ */
+static struct kvm *kvm_alloc_kvm(void)
+{
+
+	struct kvm *kvm;
+	uint64_t  vm_base;
+
+	vm_base = __get_free_pages(GFP_KERNEL, get_order(KVM_VM_DATA_SIZE));
+
+	if (!vm_base)
+		return ERR_PTR(-ENOMEM);
+	printk(KERN_DEBUG"kvm:vm data base address:0x%lx\n", vm_base);
+
+	/*
+	 * Zero all pages before use!
+	 */
+	memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
+
+	kvm = (struct kvm *)(vm_base + KVM_VM_OFS);
+	kvm->arch.vm_base = vm_base;
+
+	return kvm;
+}
+
+typedef struct kvm_io_range {
+	unsigned long start;
+	unsigned long size;
+	unsigned long type;
+} kvm_io_range_t;
+
+static const kvm_io_range_t io_ranges[] = {
+	{VGA_IO_START, VGA_IO_SIZE, GPFN_FRAME_BUFFER},
+	{MMIO_START, MMIO_SIZE, GPFN_LOW_MMIO},
+	{LEGACY_IO_START, LEGACY_IO_SIZE, GPFN_LEGACY_IO},
+	{IO_SAPIC_START, IO_SAPIC_SIZE, GPFN_IOSAPIC},
+	{PIB_START, PIB_SIZE, GPFN_PIB},
+};
+
+
+static void kvm_build_io_pmt(struct kvm *kvm)
+{
+	unsigned long i, j;
+
+	/* Mark I/O ranges */
+	for (i = 0; i < (sizeof(io_ranges) / sizeof(kvm_io_range_t)); i++) {
+		for (j = io_ranges[i].start;
+				j < io_ranges[i].start + io_ranges[i].size;
+				j += PAGE_SIZE)
+			kvm_set_pmt_entry(kvm, j >> PAGE_SHIFT,
+					io_ranges[i].type, 0);
+	}
+
+}
+
+/*Use unused rids to virtualize guest rid.*/
+#define GUEST_PHYSICAL_RR0	0x1739
+#define GUEST_PHYSICAL_RR4	0x2739
+#define VMM_INIT_RR		0x1660
+
+static void kvm_init_vm(struct kvm *kvm)
+{
+	long vm_base;
+
+	BUG_ON(!kvm);
+
+	kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
+	kvm->arch.metaphysical_rr4 = GUEST_PHYSICAL_RR4;
+	kvm->arch.vmm_init_rr = VMM_INIT_RR;
+
+	vm_base = kvm->arch.vm_base;
+	if (vm_base) {
+		kvm->arch.vhpt_base = vm_base + KVM_VHPT_OFS;
+		kvm->arch.vtlb_base = vm_base + KVM_VTLB_OFS;
+		kvm->arch.vpd_base  = vm_base + KVM_VPD_OFS;
+	}
+
+	/*
+	 *Fill P2M entries for MMIO/IO ranges
+	 */
+	kvm_build_io_pmt(kvm);
+
+}
+
+struct  kvm *kvm_arch_create_vm(void)
+{
+	struct kvm *kvm = kvm_alloc_kvm();
+
+	if (IS_ERR(kvm))
+		return ERR_PTR(-ENOMEM);
+	kvm_init_vm(kvm);
+
+	return kvm;
+
+}
+
+static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm,
+					struct kvm_irqchip *chip)
+{
+	int r;
+
+	r = 0;
+	switch (chip->chip_id) {
+	case KVM_IRQCHIP_IOAPIC:
+		memcpy(&chip->chip.ioapic, ioapic_irqchip(kvm),
+				sizeof(struct kvm_ioapic_state));
+		break;
+	default:
+		r = -EINVAL;
+		break;
+	}
+	return r;
+}
+
+static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
+{
+	int r;
+
+	r = 0;
+	switch (chip->chip_id) {
+	case KVM_IRQCHIP_IOAPIC:
+		memcpy(ioapic_irqchip(kvm),
+				&chip->chip.ioapic,
+				sizeof(struct kvm_ioapic_state));
+		break;
+	default:
+		r = -EINVAL;
+		break;
+	}
+	return r;
+}
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+	printk(KERN_WARNING"Doesn't support it yet!!\n");
+	return 0;
+}
+
+long kvm_arch_vm_ioctl(struct file *filp,
+		unsigned int ioctl, unsigned long arg)
+{
+	struct kvm *kvm = filp->private_data;
+	void __user *argp = (void __user *)arg;
+	int r = -EINVAL;
+
+	switch (ioctl) {
+	case KVM_SET_MEMORY_REGION: {
+		struct kvm_memory_region kvm_mem;
+		struct kvm_userspace_memory_region kvm_userspace_mem;
+
+		r = -EFAULT;
+		if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
+			goto out;
+		kvm_userspace_mem.slot = kvm_mem.slot;
+		kvm_userspace_mem.flags = kvm_mem.flags;
+		kvm_userspace_mem.guest_phys_addr =
+					kvm_mem.guest_phys_addr;
+		kvm_userspace_mem.memory_size = kvm_mem.memory_size;
+		r = kvm_vm_ioctl_set_memory_region(kvm,
+					&kvm_userspace_mem, 0);
+		if (r)
+			goto out;
+		break;
+		}
+	case KVM_CREATE_IRQCHIP:
+		r = -EFAULT;
+		r = kvm_ioapic_init(kvm);
+		if (r)
+			goto out;
+		break;
+	case KVM_IRQ_LINE: {
+		struct kvm_irq_level irq_event;
+
+		r = -EFAULT;
+		if (copy_from_user(&irq_event, argp, sizeof irq_event))
+			goto out;
+		if (irqchip_in_kernel(kvm)) {
+			mutex_lock(&kvm->lock);
+			kvm_ioapic_set_irq(kvm->arch.vioapic,
+						irq_event.irq,
+						irq_event.level);
+			mutex_unlock(&kvm->lock);
+			r = 0;
+		}
+		break;
+		}
+	case KVM_GET_IRQCHIP: {
+		/* 0: PIC master, 1: PIC slave, 2: IOAPIC */
+		struct kvm_irqchip chip;
+
+		r = -EFAULT;
+		if (copy_from_user(&chip, argp, sizeof chip))
+				goto out;
+		r = -ENXIO;
+		if (!irqchip_in_kernel(kvm))
+			goto out;
+		r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
+		if (r)
+			goto out;
+		r = -EFAULT;
+		if (copy_to_user(argp, &chip, sizeof chip))
+				goto out;
+		r = 0;
+		break;
+		}
+	case KVM_SET_IRQCHIP: {
+		/* 0: PIC master, 1: PIC slave, 2: IOAPIC */
+		struct kvm_irqchip chip;
+
+		r = -EFAULT;
+		if (copy_from_user(&chip, argp, sizeof chip))
+				goto out;
+		r = -ENXIO;
+		if (!irqchip_in_kernel(kvm))
+			goto out;
+		r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
+		if (r)
+			goto out;
+		r = 0;
+		break;
+		}
+	default:
+		;
+	}
+out:
+	return r;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+		struct kvm_sregs *sregs)
+{
+	printk(KERN_WARNING"kvm:kvm_arch_vcpu_ioctl_set_sregs called!!\n");
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+		struct kvm_sregs *sregs)
+{
+	printk(KERN_WARNING"kvm:kvm_arch_vcpu_ioctl_get_sregs called!!\n");
+	return 0;
+
+}
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+		struct kvm_translation *tr)
+{
+	printk(KERN_WARNING"kvm:kvm_arch_vcpu_ioctl_translate called!!\n");
+
+	return 0;
+}
+
+static int kvm_alloc_vmm_area(void)
+{
+	if (!kvm_vmm_base && (kvm_vm_buffer_size < KVM_VM_BUFFER_SIZE)) {
+		kvm_vmm_base = __get_free_pages(GFP_KERNEL,
+				get_order(KVM_VMM_SIZE));
+		if (!kvm_vmm_base)
+			return -ENOMEM;
+
+		memset((void *)kvm_vmm_base, 0, KVM_VMM_SIZE);
+		kvm_vm_buffer = kvm_vmm_base + VMM_SIZE;
+
+		printk(KERN_DEBUG"kvm:kvm_vmm_base:0x%lx, vm_buffer:0x%lx\n",
+				kvm_vmm_base, kvm_vm_buffer);
+	}
+
+	return 0;
+}
+
+static void kvm_free_vmm_area(void)
+{
+	if (kvm_vmm_base) {
+		/*Zero this area before free to avoid bits leak!!*/
+		memset((void *)kvm_vmm_base, 0, KVM_VMM_SIZE);
+		free_pages(kvm_vmm_base, get_order(KVM_VMM_SIZE));
+		kvm_vmm_base  = 0;
+		kvm_vm_buffer = 0;
+		kvm_vsa_base = 0;
+	}
+}
+
+/*
+ * Make sure that a cpu that is being hot-unplugged does not have any vcpus
+ * cached on it. Leave it as blank for IA64.
+ */
+void decache_vcpus_on_cpu(int cpu)
+{
+}
+
+static void vti_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+}
+
+static int vti_init_vpd(struct kvm_vcpu *vcpu)
+{
+	int i;
+	cpuid3_t cpuid3;
+	struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+	if (IS_ERR(vpd))
+		return PTR_ERR(vpd);
+
+	/* CPUID init */
+	for (i = 0; i < 5; i++)
+		vpd->vcpuid[i] = ia64_get_cpuid(i);
+
+	/* Limit the CPUID number to 5 */
+	cpuid3.value = vpd->vcpuid[3];
+	cpuid3.number = 4;	/* 5 - 1 */
+	vpd->vcpuid[3] = cpuid3.value;
+
+	/*Set vac and vdc fields*/
+	vpd->vac.a_from_int_cr = 1;
+	vpd->vac.a_to_int_cr = 1;
+	vpd->vac.a_from_psr = 1;
+	vpd->vac.a_from_cpuid = 1;
+	vpd->vac.a_cover = 1;
+	vpd->vac.a_bsw = 1;
+	vpd->vac.a_int = 1;
+	vpd->vdc.d_vmsw = 1;
+
+	/*Set virtual buffer*/
+	vpd->virt_env_vaddr = KVM_VM_BUFFER_BASE;
+
+	return 0;
+}
+
+static int vti_create_vp(struct kvm_vcpu *vcpu)
+{
+	long ret;
+	vpd_t *vpd = vcpu->arch.vpd;
+	unsigned long  vmm_ivt;
+
+	vmm_ivt = kvm_vmm_info->vmm_ivt;
+
+	printk(KERN_DEBUG "kvm: vcpu:%p,ivt: 0x%lx\n", vcpu, vmm_ivt);
+
+	ret = ia64_pal_vp_create((u64 *)vpd, (u64 *)vmm_ivt, 0);
+
+	if (ret) {
+		printk(KERN_ERR"kvm: ia64_pal_vp_create failed!\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void init_ptce_info(struct kvm_vcpu *vcpu)
+{
+	ia64_ptce_info_t ptce = {0};
+
+	ia64_get_ptce(&ptce);
+	vcpu->arch.ptce_base = ptce.base;
+	vcpu->arch.ptce_count[0] = ptce.count[0];
+	vcpu->arch.ptce_count[1] = ptce.count[1];
+	vcpu->arch.ptce_stride[0] = ptce.stride[0];
+	vcpu->arch.ptce_stride[1] = ptce.stride[1];
+}
+
+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	struct page *page;
+	int r;
+	struct kvm *kvm = vcpu->kvm;
+
+	context_t *p_ctx = &vcpu->arch.guest;
+	struct kvm_vcpu *vmm_vcpu = to_guest(vcpu->kvm, vcpu);
+
+	/*Init vcpu context for first run.*/
+	if (IS_ERR(vmm_vcpu))
+		return PTR_ERR(vmm_vcpu);
+
+	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+	if (!page) {
+		r = -ENOMEM;
+		goto fail;
+	}
+	vcpu->arch.pio_data = page_address(page);
+
+	if (vcpu->vcpu_id == 0)
+		vcpu->arch.mp_state = VCPU_MP_STATE_RUNNABLE;
+	else
+		vcpu->arch.mp_state = VCPU_MP_STATE_UNINITIALIZED;
+	/*FIXME:Need to removed it later!!\n*/
+	vcpu->arch.apic = kzalloc(sizeof(struct kvm_lapic), GFP_KERNEL);
+
+	p_ctx->gr[1] = 0;
+	p_ctx->gr[12] = (unsigned long)((char *)vmm_vcpu + IA64_STK_OFFSET);
+	p_ctx->gr[13] = (unsigned long)vmm_vcpu;
+	p_ctx->psr = 0x1008522000UL;
+	p_ctx->ar[40] = FPSR_DEFAULT; /*fpsr*/
+	p_ctx->caller_unat = 0;
+	p_ctx->pr = 0x0;
+	p_ctx->ar[36] = 0x0; /*unat*/
+	p_ctx->ar[19] = 0x0; /*rnat*/
+	p_ctx->ar[18] = (unsigned long)vmm_vcpu +
+				((sizeof(struct kvm_vcpu)+15) & ~15);
+	p_ctx->ar[64] = 0x0; /*pfs*/
+	p_ctx->cr[0] = 0x7e04UL;
+	p_ctx->cr[2] = (unsigned long)kvm_vmm_info->vmm_ivt;
+	p_ctx->cr[8] = 0x3c;
+
+	/*Initilize region register*/
+	p_ctx->rr[0] = 0x30;
+	p_ctx->rr[1] = 0x30;
+	p_ctx->rr[2] = 0x30;
+	p_ctx->rr[3] = 0x30;
+	p_ctx->rr[4] = 0x30;
+	p_ctx->rr[5] = 0x30;
+	p_ctx->rr[7] = 0x30;
+
+	/*Initilize branch register 0*/
+	p_ctx->br[0] = *(unsigned long *)kvm_vmm_info->vmm_entry;
+
+	vcpu->arch.vmm_rr = kvm->arch.vmm_init_rr;
+	vcpu->arch.metaphysical_rr0 = kvm->arch.metaphysical_rr0;
+	vcpu->arch.metaphysical_rr4 = kvm->arch.metaphysical_rr4;
+
+	vcpu->arch.vpd = (vpd_t *)VPD_ADDR(vcpu->vcpu_id);
+	vcpu->arch.vsa_base = kvm_vsa_base;
+	vcpu->arch.__gp = kvm_vmm_gp;
+	vcpu->arch.vhpt.hash = (thash_data_t *)VHPT_ADDR(vcpu->vcpu_id);
+	vcpu->arch.vtlb.hash = (thash_data_t *)VTLB_ADDR(vcpu->vcpu_id);
+	init_ptce_info(vcpu);
+
+	return 0;
+fail:
+	return r;
+}
+
+static int vti_vcpu_setup(struct kvm_vcpu *vcpu, int id)
+{
+	unsigned long psr;
+	int r;
+
+	local_irq_save(psr);
+	kvm_insert_vmm_mapping(vcpu);
+
+	r = kvm_vcpu_init(vcpu, vcpu->kvm, id);
+	if (r)
+		goto fail;
+
+	r = vti_init_vpd(vcpu);
+	if (r) {
+		printk(KERN_DEBUG"kvm: vpd init error!!\n");
+		goto uninit;
+	}
+
+	r = vti_create_vp(vcpu);
+	if (r)
+		goto uninit;
+
+	kvm_purge_vmm_mapping();
+	local_irq_restore(psr);
+
+	return 0;
+uninit:
+	kvm_vcpu_uninit(vcpu);
+fail:
+	return r;
+}
+
+struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
+		unsigned int id)
+{
+	struct kvm_vcpu *vcpu;
+	unsigned long vm_base = kvm->arch.vm_base;
+	int r;
+	int cpu;
+
+	r = -ENOMEM;
+	if (!vm_base) {
+		printk(KERN_ERR"kvm: Create vcpu[%d] error!\n", id);
+		goto fail;
+	}
+	vcpu = (struct kvm_vcpu *)(vm_base + KVM_VCPU_OFS + VCPU_SIZE * id);
+	vcpu->kvm = kvm;
+
+	cpu = get_cpu();
+	vti_vcpu_load(vcpu, cpu);
+	r = vti_vcpu_setup(vcpu, id);
+	put_cpu();
+
+	if (r) {
+		printk(KERN_DEBUG"kvm: vcpu_setup error!!\n");
+		goto fail;
+	}
+
+	return vcpu;
+fail:
+	return ERR_PTR(r);
+}
+
+int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+	printk(KERN_WARNING"kvm:IA64 doesn't need to export"
+			"fpu to userspace!\n");
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+	printk(KERN_WARNING"kvm:IA64 doesn't need to export"
+					"fpu to userspace !\n");
+	return 0;
+}
+
+int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
+		struct kvm_debug_guest *dbg)
+{
+	printk(KERN_INFO"Not Implemented yet!\n");
+	return 0;
+}
+
+static void free_kvm(struct kvm *kvm)
+{
+	unsigned long vm_base = kvm->arch.vm_base;
+
+	if (vm_base) {
+		memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
+		free_pages(vm_base, get_order(KVM_VM_DATA_SIZE));
+	}
+
+}
+
+/*FIXME:Remove it once swapping ready!*/
+static void kvm_release_vm_pages(struct kvm *kvm)
+{
+	struct kvm_memory_slot *memslot;
+	int i, j;
+	unsigned long base_gfn;
+
+	for (i = 0; i < kvm->nmemslots; i++) {
+		memslot = &kvm->memslots[i];
+		base_gfn = memslot->base_gfn;
+
+		for (j = 0; j < memslot->npages; j++) {
+			if (memslot->rmap[j])
+				put_page((struct page *)memslot->rmap[j]);
+		}
+	}
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+	kfree(kvm->arch.vioapic);
+	kvm_release_vm_pages(kvm);
+	kvm_free_physmem(kvm);
+	free_kvm(kvm);
+}
+
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+	/*FIXME: To Implement!!*/
+}
+
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+
+	/*FIXME: To Implement!!*/
+}
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+	printk(KERN_INFO"No need to implment on IA64!\n");
+	return 0;
+}
+
+void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+	free_page((unsigned long)vcpu->arch.pio_data);
+	kfree(vcpu->arch.apic);
+}
+
+
+long kvm_arch_vcpu_ioctl(struct file *filp,
+		unsigned int ioctl, unsigned long arg)
+{
+	return -EINVAL;
+}
+
+int kvm_arch_set_memory_region(struct kvm *kvm,
+		struct kvm_userspace_memory_region *mem,
+		struct kvm_memory_slot old,
+		int user_alloc)
+{
+	unsigned long i;
+	struct page *page;
+	int npages = mem->memory_size >> PAGE_SHIFT;
+	struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot];
+	unsigned long base_gfn = memslot->base_gfn;
+
+	for (i = 0; i < npages; i++) {
+		page = gfn_to_page(kvm, base_gfn + i);
+		kvm_set_pmt_entry(kvm, base_gfn + i,
+				page_to_pfn(page) << PAGE_SHIFT,
+				_PAGE_AR_RWX|_PAGE_MA_WB);
+		memslot->rmap[i] = (unsigned long)page;
+	}
+
+	return 0;
+}
+
+
+long kvm_arch_dev_ioctl(struct file *filp,
+		unsigned int ioctl, unsigned long arg)
+{
+	return -EINVAL;
+}
+
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+	kvm_vcpu_uninit(vcpu);
+}
+
+static int vti_cpu_has_kvm_support(void)
+{
+	long  avail = 1, status = 1, control = 1;
+	long ret;
+
+	ret = ia64_pal_proc_get_features(&avail, &status, &control, 0);
+	if (ret)
+		goto out;
+
+	if (!(avail & PAL_PROC_VM_BIT))
+		goto out;
+
+	printk(KERN_DEBUG"kvm: Hardware Supports VT\n");
+
+	ret = ia64_pal_vp_env_info(&kvm_vm_buffer_size, &vp_env_info);
+	if (ret)
+		goto out;
+	printk(KERN_DEBUG"kvm: vm buffer size:0x%lx\n", kvm_vm_buffer_size);
+
+	if (!(vp_env_info & VP_OPCODE)) {
+		printk(KERN_WARNING"No opcode ability on hardware,\
+				vm_env_info:0x%lx\n",vp_env_info);
+	}
+
+	return 1;
+out:
+	return 0;
+}
+
+static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
+						struct module *module)
+{
+	unsigned long module_base;
+	unsigned long vmm_size;
+
+	unsigned long vmm_offset, func_offset, fdesc_offset;
+	struct fdesc *p_fdesc;
+
+	BUG_ON(!module);
+
+	if (!kvm_vmm_base) {
+		printk("kvm: kvm area didn't initilize yet!!\n");
+		return -EINVAL;
+	}
+
+	/*Calculate new position of relocated vmm module.*/
+	module_base = (unsigned long)module->module_core;
+	vmm_size = module->core_size;
+	if (unlikely(vmm_size > KVM_VMM_SIZE))
+		return -EFAULT;
+
+	memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size);
+	kvm_flush_icache(kvm_vmm_base, vmm_size);
+
+	/*Recalculate kvm_vmm_info based on new VMM*/
+	vmm_offset = vmm_info->vmm_ivt - module_base;
+	kvm_vmm_info->vmm_ivt = KVM_VMM_BASE + vmm_offset;
+	printk(KERN_DEBUG"kvm: Relocated VMM ivt base addr:%lx\n",
+			kvm_vmm_info->vmm_ivt);
+
+	fdesc_offset = (unsigned long)vmm_info->vmm_entry - module_base;
+	kvm_vmm_info->vmm_entry = (kvm_vmm_entry *)(KVM_VMM_BASE +
+							fdesc_offset);
+	func_offset = *(unsigned long *)vmm_info->vmm_entry - module_base;
+	p_fdesc = (struct fdesc *)(kvm_vmm_base + fdesc_offset);
+	p_fdesc->ip = KVM_VMM_BASE + func_offset;
+	p_fdesc->gp = KVM_VMM_BASE+(p_fdesc->gp - module_base);
+
+	printk(KERN_DEBUG"Guest VMM init entry addr:%lx\n",
+			KVM_VMM_BASE+func_offset);
+
+	fdesc_offset = (unsigned long)vmm_info->tramp_entry - module_base;
+	kvm_vmm_info->tramp_entry = (kvm_tramp_entry *)(KVM_VMM_BASE +
+			fdesc_offset);
+	func_offset = *(unsigned long *)vmm_info->tramp_entry - module_base;
+	p_fdesc = (struct fdesc *)(kvm_vmm_base + fdesc_offset);
+	p_fdesc->ip = KVM_VMM_BASE + func_offset;
+	p_fdesc->gp = KVM_VMM_BASE + (p_fdesc->gp - module_base);
+
+	kvm_vmm_gp = p_fdesc->gp;
+
+	printk(KERN_DEBUG"kvm: vmm's fdesc:%p\n", p_fdesc);
+	printk(KERN_DEBUG"kvm: vmm_entry ip:%p\n", kvm_vmm_info->vmm_entry);
+	printk(KERN_DEBUG"kvm: vmm trampoline entry ip:0x%lx\n",
+						KVM_VMM_BASE + func_offset);
+
+	return 0;
+}
+
+int kvm_arch_init(void *opaque)
+{
+	int r;
+	struct kvm_vmm_info *vmm_info = (struct kvm_vmm_info *)opaque;
+
+	if (kvm_vmm_info) {
+		printk(KERN_ERR "kvm: already loaded the other module!\n");
+		r = -EEXIST;
+		goto out;
+	}
+
+	r =  -ENOMEM;
+	kvm_vmm_info = kzalloc(sizeof(struct kvm_vmm_info), GFP_KERNEL);
+	if (!kvm_vmm_info)
+		goto out;
+
+	if (!vti_cpu_has_kvm_support()) {
+		printk(KERN_ERR "kvm: no hardware support\n");
+		r = -EOPNOTSUPP;
+		goto out_free0;
+	}
+
+	kvm_hack_insert_tr();
+
+	if (kvm_alloc_vmm_area())
+		goto out_free0;
+
+	r = kvm_relocate_vmm(vmm_info, vmm_info->module);
+	if (r)
+		goto out_free1;
+
+	return 0;
+
+out_free1:
+	kvm_free_vmm_area();
+out_free0:
+	kfree(kvm_vmm_info);
+out:
+	return r;
+}
+
+void kvm_arch_exit(void)
+{
+	kvm_free_vmm_area();
+	kfree(kvm_vmm_info);
+	kvm_vmm_info = 0;
+}
+
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
+		struct kvm_dirty_log *log)
+{
+	printk(KERN_WARNING"Need to implement later!\n");
+	return 0;
+}
+
+int kvm_arch_hardware_setup(void)
+{
+	return 0;
+}
+
+void kvm_arch_hardware_unsetup(void)
+{
+}
+
+static void vcpu_kick_intr(void *info)
+{
+#ifdef DEBUG
+	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)info;
+	printk(KERN_DEBUG"vcpu_kick_intr %p \n", vcpu);
+#endif
+}
+
+void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
+{
+	int ipi_pcpu = vcpu->cpu;
+
+	if (waitqueue_active(&vcpu->wq)) {
+		wake_up_interruptible(&vcpu->wq);
+	}
+	if (vcpu->guest_mode)
+		smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0, 0);
+}
+
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
+{
+
+	struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+	if (!test_and_set_bit(vec, &vpd->irr[0])) {
+		vcpu->arch.irq_new_pending = 1;
+		kvm_vcpu_kick(vcpu);
+		return 1;
+	}
+	return 0;
+}
+
+int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest)
+{
+	return 1;
+}
+
+int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
+{
+	return 0;
+}
+
+struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
+				       unsigned long bitmap)
+{
+	struct kvm_vcpu *lvcpu = kvm->vcpus[0];
+	int i;
+
+	for (i = 1; i < KVM_MAX_VCPUS; i++) {
+		if (!kvm->vcpus[i])
+			continue;
+		if (lvcpu->arch.xtp > kvm->vcpus[i]->arch.xtp)
+			lvcpu = kvm->vcpus[i];
+	}
+
+	return lvcpu;
+}
+
+static int find_highest_bits(int *dat)
+{
+	u32  bits, bitnum;
+	int i;
+
+	/* loop for all 256 bits */
+	for (i = 7; i >= 0 ; i--) {
+		bits = dat[i];
+		if (bits) {
+			bitnum = fls(bits);
+			return i * 32 + bitnum - 1;
+		}
+	}
+
+	return -1;
+}
+
+int kvm_highest_pending_irq(struct kvm_vcpu *vcpu)
+{
+    struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+
+    if (vpd->irr[0] & (1UL << NMI_VECTOR))
+		return NMI_VECTOR;
+    if (vpd->irr[0] & (1UL << ExtINT_VECTOR))
+		return ExtINT_VECTOR;
+
+    return find_highest_bits((int *)&vpd->irr[0]);
+}
+
+int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)
+{
+	if (kvm_highest_pending_irq(vcpu) != -1)
+		return 1;
+	return 0;
+}
+
+gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
+{
+	return gfn;
+}
+
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.mp_state == VCPU_MP_STATE_RUNNABLE
+	       || vcpu->arch.mp_state == VCPU_MP_STATE_SIPI_RECEIVED;
+}
+
-- 
1.5.2


[-- Attachment #4: 0003-kvm-ia64-Add-kvm-sal-pal-virtulization-support.patch --]
[-- Type: application/octet-stream, Size: 11809 bytes --]

From 38b4327349c93908adca64626969005853240830 Mon Sep 17 00:00:00 2001
From: Zhang Xiantao <xiantao.zhang@intel.com>
Date: Thu, 20 Dec 2007 09:37:41 +0800
Subject: [PATCH] kvm/ia64: Add kvm sal/pal virtulization support.

Some sal/pal calls would be traped to kvm for virtulization
from guest firmware.
Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com>
---
 arch/ia64/kvm/kvm_fw.c |  457 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 457 insertions(+), 0 deletions(-)
 create mode 100644 arch/ia64/kvm/kvm_fw.c

diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c
new file mode 100644
index 0000000..540b6f6
--- /dev/null
+++ b/arch/ia64/kvm/kvm_fw.c
@@ -0,0 +1,457 @@
+/*
+ * PAL/SAL call delegation
+ *
+ * Copyright (c) 2004 Li Susie <susie.li@intel.com>
+ * Copyright (c) 2005 Yu Ke <ke.yu@intel.com>
+ * Copyright (c) 2007 Zhang Xiantao <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <linux/kvm_host.h>
+
+#include "vti.h"
+#include "misc.h"
+
+#include <asm/pal.h>
+#include <asm/sal.h>
+#include <asm/tlb.h>
+
+/*
+ * Handy macros to make sure that the PAL return values start out
+ * as something meaningful.
+ */
+#define INIT_PAL_STATUS_UNIMPLEMENTED(x)		\
+	{						\
+		x.status = PAL_STATUS_UNIMPLEMENTED;	\
+		x.v0 = 0;				\
+		x.v1 = 0;				\
+		x.v2 = 0;				\
+	}
+
+#define INIT_PAL_STATUS_SUCCESS(x)			\
+	{						\
+		x.status = PAL_STATUS_SUCCESS;		\
+		x.v0 = 0;				\
+		x.v1 = 0;				\
+		x.v2 = 0;				\
+    }
+
+static void kvm_get_pal_call_data(struct kvm_vcpu *vcpu,
+		u64 *gr28, u64 *gr29, u64 *gr30, u64 *gr31) {
+	struct exit_ctl_data *p;
+
+	if (vcpu) {
+		p = &vcpu->arch.exit_data;
+		if (p->exit_reason == EXIT_REASON_PAL_CALL) {
+			*gr28 = p->u.pal_data.gr28;
+			*gr29 = p->u.pal_data.gr29;
+			*gr30 = p->u.pal_data.gr30;
+			*gr31 = p->u.pal_data.gr31;
+			return ;
+		}
+	}
+	printk(KERN_DEBUG"Error occurs in kvm_get_pal_call_data!!\n");
+}
+
+static void set_pal_result(struct kvm_vcpu *vcpu,
+		struct ia64_pal_retval result) {
+
+	struct exit_ctl_data *p;
+
+	p = kvm_get_exit_data(vcpu);
+	if (p && p->exit_reason == EXIT_REASON_PAL_CALL) {
+		p->u.pal_data.ret = result;
+		return ;
+	}
+	INIT_PAL_STATUS_UNIMPLEMENTED(p->u.pal_data.ret);
+}
+
+static void set_sal_result(struct kvm_vcpu *vcpu,
+		struct sal_ret_values result) {
+	struct exit_ctl_data *p;
+
+	p = kvm_get_exit_data(vcpu);
+	if (p && p->exit_reason == EXIT_REASON_SAL_CALL) {
+		p->u.sal_data.ret = result;
+		return ;
+	}
+	printk(KERN_WARNING"Error occurs!!!\n");
+}
+
+
+
+static struct ia64_pal_retval pal_cache_flush(struct kvm_vcpu *vcpu)
+{
+	u64 gr28, gr29, gr30, gr31;
+	struct ia64_pal_retval result;
+
+	gr28 = gr29 = gr30 = gr31 = 0;
+	kvm_get_pal_call_data(vcpu, &gr28, &gr29, &gr30, &gr31);
+
+	/* Always call Host Pal in int=1 */
+	gr30 = gr30 & ~0x2UL;
+
+	/*
+	 * Call Host PAL cache flush
+	 * Clear psr.ic when call PAL_CACHE_FLUSH
+	 */
+	result = ia64_pal_call_static(gr28, gr29, gr30, gr31);
+
+	/* If host PAL call is interrupted, then loop to complete it.
+		while (result.status == 1)
+			ia64_pal_call_static(gr28, gr29, gr30, result.v1, 1LL);
+	*/
+
+	return result;
+}
+
+struct ia64_pal_retval pal_cache_summary(struct kvm_vcpu *vcpu)
+{
+
+	struct ia64_pal_retval result;
+
+	PAL_CALL(result, PAL_CACHE_SUMMARY, 0, 0, 0);
+	return result;
+}
+
+static struct ia64_pal_retval pal_freq_base(struct kvm_vcpu *vcpu)
+{
+
+	struct ia64_pal_retval result;
+
+	PAL_CALL(result, PAL_FREQ_BASE, 0, 0, 0);
+
+	/*
+	 * PAL_FREQ_BASE may not be implemented in some platforms,
+	 * call SAL instead.
+	 */
+	if (result.v0 == 0) {
+		result.status = ia64_sal_freq_base(SAL_FREQ_BASE_PLATFORM,
+							&result.v0,
+							&result.v1);
+		result.v2 = 0;
+	}
+
+	return result;
+}
+
+static struct ia64_pal_retval pal_freq_ratios(struct kvm_vcpu *vcpu)
+{
+
+	struct ia64_pal_retval result;
+
+	PAL_CALL(result, PAL_FREQ_RATIOS, 0, 0, 0);
+	return result;
+}
+
+static struct ia64_pal_retval pal_logical_to_physica(struct kvm_vcpu *vcpu)
+{
+	struct ia64_pal_retval result;
+
+	INIT_PAL_STATUS_UNIMPLEMENTED(result);
+	return result;
+}
+
+static struct ia64_pal_retval pal_platform_addr(struct kvm_vcpu *vcpu)
+{
+
+	struct ia64_pal_retval result;
+
+	INIT_PAL_STATUS_SUCCESS(result);
+	return result;
+}
+
+static struct ia64_pal_retval pal_proc_get_features(struct kvm_vcpu *vcpu)
+{
+
+	struct ia64_pal_retval result = {0, 0, 0, 0};
+	long in0, in1, in2, in3;
+
+	kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+	result.status = ia64_pal_proc_get_features(&result.v0, &result.v1,
+			&result.v2, in2);
+
+	return result;
+}
+
+static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu)
+{
+
+	pal_cache_config_info_t ci;
+	long status;
+	unsigned long in0, in1, in2, in3, r9, r10;
+
+	kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3);
+	status = ia64_pal_cache_config_info(in1, in2, &ci);
+	r9 = ci.pcci_info_1.pcci1_data;
+	r10 = ci.pcci_info_2.pcci2_data;
+	return ((struct ia64_pal_retval){status, r9, r10, 0});
+}
+
+#define GUEST_IMPL_VA_MSB	59
+#define GUEST_RID_BITS		18
+
+static struct ia64_pal_retval pal_vm_summary(struct kvm_vcpu *vcpu)
+{
+
+	pal_vm_info_1_u_t vminfo1;
+	pal_vm_info_2_u_t vminfo2;
+	struct ia64_pal_retval result;
+
+	PAL_CALL(result, PAL_VM_SUMMARY, 0, 0, 0);
+	if (!result.status) {
+		vminfo1.pvi1_val = result.v0;
+		vminfo1.pal_vm_info_1_s.max_itr_entry = 8;
+		vminfo1.pal_vm_info_1_s.max_dtr_entry = 8;
+		result.v0 = vminfo1.pvi1_val;
+		vminfo2.pal_vm_info_2_s.impl_va_msb = GUEST_IMPL_VA_MSB;
+		vminfo2.pal_vm_info_2_s.rid_size = GUEST_RID_BITS;
+		result.v1 = vminfo2.pvi2_val;
+	}
+
+	return result;
+}
+
+static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu)
+{
+	struct ia64_pal_retval result;
+
+	INIT_PAL_STATUS_UNIMPLEMENTED(result);
+
+	return result;
+}
+
+static  u64 kvm_get_pal_call_index(struct kvm_vcpu *vcpu)
+{
+	u64 index = 0;
+	struct exit_ctl_data *p;
+
+	p = kvm_get_exit_data(vcpu);
+	if (p && (p->exit_reason == EXIT_REASON_PAL_CALL)) {
+		index = p->u.pal_data.gr28;
+	}
+	return index;
+}
+
+int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+
+	u64 gr28;
+	struct ia64_pal_retval result;
+	int ret = 1;
+
+	gr28 = kvm_get_pal_call_index(vcpu);
+	/*printk("pal_call index:%lx\n",gr28);*/
+	switch (gr28) {
+	case PAL_CACHE_FLUSH:
+		result = pal_cache_flush(vcpu);
+		break;
+	case PAL_CACHE_SUMMARY:
+		result = pal_cache_summary(vcpu);
+		break;
+	case PAL_HALT_LIGHT:
+	{
+		vcpu->arch.timer_check = 1;
+		if (kvm_highest_pending_irq(vcpu) == -1) {
+			ret = kvm_emulate_halt(vcpu);
+		}
+		INIT_PAL_STATUS_SUCCESS(result);
+	}
+		break;
+
+	case PAL_FREQ_RATIOS:
+		result = pal_freq_ratios(vcpu);
+		break;
+
+	case PAL_FREQ_BASE:
+		result = pal_freq_base(vcpu);
+		break;
+
+	case PAL_LOGICAL_TO_PHYSICAL :
+		result = pal_logical_to_physica(vcpu);
+		break;
+
+	case PAL_VM_SUMMARY :
+		result = pal_vm_summary(vcpu);
+		break;
+
+	case PAL_VM_INFO :
+		result = pal_vm_info(vcpu);
+		break;
+	case PAL_PLATFORM_ADDR :
+		result = pal_platform_addr(vcpu);
+		break;
+	case PAL_CACHE_INFO:
+		result = pal_cache_info(vcpu);
+		break;
+	case PAL_PTCE_INFO:
+		INIT_PAL_STATUS_SUCCESS(result);
+		result.v1 = (1L << 32) | 1L;
+		break;
+	case PAL_VM_PAGE_SIZE:
+		result.status = ia64_pal_vm_page_size(&result.v0,
+							&result.v1);
+		break;
+	case PAL_RSE_INFO:
+		result.status = ia64_pal_rse_info(&result.v0,
+					(pal_hints_u_t *)&result.v1);
+		break;
+	case PAL_PROC_GET_FEATURES:
+		result = pal_proc_get_features(vcpu);
+		break;
+	case PAL_DEBUG_INFO:
+		result.status = ia64_pal_debug_info(&result.v0,
+							&result.v1);
+		break;
+	case PAL_VERSION:
+		result.status = ia64_pal_version(
+				(pal_version_u_t *)&result.v0,
+				(pal_version_u_t *)&result.v1);
+
+		break;
+	case PAL_FIXED_ADDR:
+		result.status = PAL_STATUS_SUCCESS;
+		result.v0 = vcpu->vcpu_id;
+		break;
+	default:
+		INIT_PAL_STATUS_UNIMPLEMENTED(result);
+		printk(KERN_WARNING"kvm: Unsupported pal call,"
+					" index:0x%lx\n", gr28);
+	}
+	set_pal_result(vcpu, result);
+	return ret;
+}
+
+static struct sal_ret_values sal_emulator(long index, unsigned long in1,
+				unsigned long in2, unsigned long in3,
+				unsigned long in4, unsigned long in5,
+				unsigned long in6, unsigned long in7)
+{
+	unsigned long r9  = 0;
+	unsigned long r10 = 0;
+	long r11 = 0;
+	long status;
+
+	status = 0;
+	switch (index) {
+	case SAL_FREQ_BASE:
+		status = ia64_sal_freq_base(in1, &r9, &r10);
+		break;
+	case SAL_PCI_CONFIG_READ:
+		printk(KERN_WARNING"kvm: Not allowed to call here!"
+			" SAL_PCI_CONFIG_READ\n");
+		break;
+	case SAL_PCI_CONFIG_WRITE:
+		printk(KERN_WARNING"kvm: Not allowed to call here!"
+			" SAL_PCI_CONFIG_WRITE\n");
+		break;
+	case SAL_SET_VECTORS:
+		if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) {
+			printk(KERN_WARNING"kvm: SAL_VECTOR_OS_BOOT_RENDEZ"
+						"not implemented !!!\n");
+		} else
+			printk(KERN_WARNING"kvm: CALLED SAL_SET_VECTORS %lu."
+							"ignored...\n", in1);
+		break;
+	case SAL_GET_STATE_INFO:
+		/* No more info.  */
+		status = -5;
+		r9 = 0;
+		break;
+	case SAL_GET_STATE_INFO_SIZE:
+		/* Return a dummy size.  */
+		status = 0;
+		r9 = 128;
+		break;
+	case SAL_CLEAR_STATE_INFO:
+		/* Noop.  */
+		break;
+	case SAL_MC_RENDEZ:
+		printk(KERN_WARNING
+			"kvm: called SAL_MC_RENDEZ. ignored...\n");
+		break;
+	case SAL_MC_SET_PARAMS:
+		printk(KERN_WARNING
+			"kvm: called  SAL_MC_SET_PARAMS.ignored!\n");
+		break;
+	case SAL_CACHE_FLUSH:
+		if (1) {
+			/*Flush using SAL.
+			This method is faster but has a side
+			effect on other vcpu running on
+			this cpu.  */
+			status = ia64_sal_cache_flush(in1);
+		} else {
+			/*Maybe need to implement the method
+			without side effect!*/
+			status = 0;
+		}
+		break;
+	case SAL_CACHE_INIT:
+		printk(KERN_WARNING
+			"kvm: called SAL_CACHE_INIT.  ignored...\n");
+		break;
+	case SAL_UPDATE_PAL:
+		printk(KERN_WARNING
+			"kvm: CALLED SAL_UPDATE_PAL.  ignored...\n");
+		break;
+	default:
+		printk(KERN_WARNING"kvm: called SAL_CALL with unknown index."
+						" index:%d\n", index);
+		status = -1;
+		break;
+	}
+	return ((struct sal_ret_values) {status, r9, r10, r11});
+}
+
+static void kvm_get_sal_call_data(struct kvm_vcpu *vcpu, u64 *in0, u64 *in1,
+		u64 *in2, u64 *in3, u64 *in4, u64 *in5, u64 *in6, u64 *in7){
+
+	struct exit_ctl_data *p;
+
+	p = kvm_get_exit_data(vcpu);
+
+	if (p) {
+		if (p->exit_reason == EXIT_REASON_SAL_CALL) {
+			*in0 = p->u.sal_data.in0;
+			*in1 = p->u.sal_data.in1;
+			*in2 = p->u.sal_data.in2;
+			*in3 = p->u.sal_data.in3;
+			*in4 = p->u.sal_data.in4;
+			*in5 = p->u.sal_data.in5;
+			*in6 = p->u.sal_data.in6;
+			*in7 = p->u.sal_data.in7;
+			return ;
+		}
+	}
+	*in0 = 0;
+}
+
+void kvm_sal_emul(struct kvm_vcpu *vcpu)
+{
+
+	struct sal_ret_values result;
+	u64 index, in1, in2, in3, in4, in5, in6, in7;
+
+	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
+			&in3, &in4, &in5, &in6, &in7);
+	if (index) {
+		result = sal_emulator(index, in1, in2, in3,
+						in4, in5, in6, in7);
+		set_sal_result(vcpu, result);
+	} else
+		printk(KERN_WARNING"kvm:Unsupported sal call called,"
+					" index:%d!\n", index);
+}
-- 
1.5.2


[-- Attachment #5: 0004-kvm-ia64-Add-tr-operation-routines-for-ia64.patch --]
[-- Type: application/octet-stream, Size: 2665 bytes --]

From d6ef7d7f5ac4867c760d0fccf89b3d4de6e09af6 Mon Sep 17 00:00:00 2001
From: Zhang Xiantao <xiantao.zhang@intel.com>
Date: Wed, 19 Dec 2007 14:14:21 +0800
Subject: [PATCH] kvm/ia64: Add tr operation routines for ia64.

This patches creates kvm_tr.S, which used as tr operations(insert/purge).
Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com>
---
 arch/ia64/kvm/kvm_tr.S |   82 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 82 insertions(+), 0 deletions(-)
 create mode 100644 arch/ia64/kvm/kvm_tr.S

diff --git a/arch/ia64/kvm/kvm_tr.S b/arch/ia64/kvm/kvm_tr.S
new file mode 100644
index 0000000..c48cac0
--- /dev/null
+++ b/arch/ia64/kvm/kvm_tr.S
@@ -0,0 +1,82 @@
+/*
+ * kvm_tr.S: Utility for TR operation
+ *
+ * 	Copyright (C) 2007 Intel Corperation
+ * 	Zhang Xiantao <xiantao.zhang@intel.com>
+ *
+ * This program is free software you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <asm/asmmacro.h>
+
+/*  __kvm_insert_idtr(trnum, vaddr, paddr, ps)
+ *  Ensure irq is disabled before called here!!!
+ *  Description:  Insert mapping into ITR & DTR with current region ID.
+ *  trnum: tr number
+ *  vaddr: virtual address (format refers to IFA format, in SDV Vol2 4.1.1.5
+ *  paddr: physical address (format refers to GR format, in SDV Vol2 4.1.1.5
+ *  ps: log 2 of page size
+ */
+GLOBAL_ENTRY (__kvm_insert_idtr)
+    .regstk 4,0,0,0
+	rsm	psr.ic
+	;;
+	srlz.d
+	;;
+	shl	in3=in3, 2
+	;;
+	mov	cr.itir=in3
+	mov	cr.ifa=in1
+	;;
+    	ptr.i in1,in3
+    	;;
+    	srlz.i
+    	;;
+	itr.i	itr[in0]=in2
+	;;
+	srlz.i
+	;;
+    	ptr.d in1,in3
+    	;;
+    	srlz.d
+    	;;
+	itr.d	dtr[in0]=in2
+	;;
+	srlz.d
+	;;
+	ssm psr.ic
+	;;
+	srlz.d
+	;;
+	br.ret.sptk b0
+END(__kvm_insert_idtr)
+
+ /*  __kvm_purge_dtr_rr(vaddr, ps,)
+ *  vaddr: virtual address (format refers to IFA format, in SDV Vol2 4.1.1.5
+ *  ps: log 2 of page size
+ */
+
+GLOBAL_ENTRY(__kvm_purge_idtr)
+    .regstk 2,0,0,0
+	shl in1 = in1,2
+	;;
+	ptr.i in0,in1
+	;;
+	srlz.i
+	ptr.d in0,in1
+	;;
+	srlz.d
+	;;
+	br.ret.sptk b0
+END(__kvm_purge_idtr)
+
-- 
1.5.2


[-- Attachment #6: 0005-kvm-ia64-Add-head-files-for-kvm-ia64.patch --]
[-- Type: application/octet-stream, Size: 51149 bytes --]

From 91ba1aa6ee18a28526d7026b65243be41ec3422e Mon Sep 17 00:00:00 2001
From: Zhang Xiantao <xiantao.zhang@intel.com>
Date: Wed, 19 Dec 2007 14:41:38 +0800
Subject: [PATCH] kvm/ia64 : Add head files for kvm/ia64

ia64_regs: some defintions for special registers which aren't defined in
asm-ia64/ia64regs.
kvm_minstate.h : Marcos about Min save routines
lapic.h: apic structure definition.
vcpu.h : routions related to vcpu virtualization.
vti.h  : Some macros or routines for VT support on Itanium.
Signed-off-by: Zhang Xiantao <xiantao.zhang@intel.com>
---
 arch/ia64/kvm/ia64_regs.h    |  235 ++++++++++++
 arch/ia64/kvm/kvm_minstate.h |  273 ++++++++++++++
 arch/ia64/kvm/lapic.h        |   27 ++
 arch/ia64/kvm/misc.h         |   95 +++++
 arch/ia64/kvm/vcpu.h         |  807 ++++++++++++++++++++++++++++++++++++++++++
 arch/ia64/kvm/vti.h          |  293 +++++++++++++++
 6 files changed, 1730 insertions(+), 0 deletions(-)
 create mode 100644 arch/ia64/kvm/ia64_regs.h
 create mode 100644 arch/ia64/kvm/kvm_minstate.h
 create mode 100644 arch/ia64/kvm/lapic.h
 create mode 100644 arch/ia64/kvm/misc.h
 create mode 100644 arch/ia64/kvm/vcpu.h
 create mode 100644 arch/ia64/kvm/vti.h

diff --git a/arch/ia64/kvm/ia64_regs.h b/arch/ia64/kvm/ia64_regs.h
new file mode 100644
index 0000000..b1693a7
--- /dev/null
+++ b/arch/ia64/kvm/ia64_regs.h
@@ -0,0 +1,235 @@
+#ifndef _KVM_ASM_IA64_REGS_H
+#define _KVM_ASM_IA64_REGS_H
+/*
+ * ia64 processor definition
+ *
+ * Copyright (C) 2007 Intel Co.
+ * 	Xuefei Xu(Anthony Xu) <anthony.xu@intel.com>
+ *
+ */
+
+#include <asm/ia64regs.h>
+#include <asm/kregs.h>
+
+#ifndef __ASSEMBLY__
+
+#include <asm/gcc_intrin.h>
+
+/* like above but expressed as bitfields for more efficient access: */
+typedef union {
+	unsigned long val;
+	struct {
+		unsigned long reserved0 : 1;
+		unsigned long be : 1;
+		unsigned long up : 1;
+		unsigned long ac : 1;
+		unsigned long mfl : 1;
+		unsigned long mfh : 1;
+		unsigned long reserved1 : 7;
+		unsigned long ic : 1;
+		unsigned long i : 1;
+		unsigned long pk : 1;
+		unsigned long reserved2 : 1;
+		unsigned long dt : 1;
+		unsigned long dfl : 1;
+		unsigned long dfh : 1;
+		unsigned long sp : 1;
+		unsigned long pp : 1;
+		unsigned long di : 1;
+		unsigned long si : 1;
+		unsigned long db : 1;
+		unsigned long lp : 1;
+		unsigned long tb : 1;
+		unsigned long rt : 1;
+		unsigned long reserved3 : 4;
+		unsigned long cpl : 2;
+		unsigned long is : 1;
+		unsigned long mc : 1;
+		unsigned long it : 1;
+		unsigned long id : 1;
+		unsigned long da : 1;
+		unsigned long dd : 1;
+		unsigned long ss : 1;
+		unsigned long ri : 2;
+		unsigned long ed : 1;
+		unsigned long bn : 1;
+		unsigned long ia : 1;
+		unsigned long vm : 1;
+		unsigned long reserved5 : 17;
+	};
+} ia64_psr;
+
+typedef union {
+	unsigned long val;
+	struct {
+		unsigned long code : 16;
+		unsigned long vector : 8;
+		unsigned long reserved1 : 8;
+		unsigned long x : 1;
+		unsigned long w : 1;
+		unsigned long r : 1;
+		unsigned long na : 1;
+		unsigned long sp : 1;
+		unsigned long rs : 1;
+		unsigned long ir : 1;
+		unsigned long ni : 1;
+		unsigned long so : 1;
+		unsigned long ei : 2;
+		unsigned long ed : 1;
+		unsigned long reserved2 : 20;
+	};
+} ia64_isr;
+
+typedef union {
+	unsigned long val;
+	struct {
+		unsigned long  rv  : 16;
+		unsigned long  eid : 8;
+		unsigned long  id  : 8;
+		unsigned long  ig  : 32;
+	};
+} ia64_lid_t;
+
+typedef union {
+	unsigned long val;
+	struct {
+		unsigned long ig0 : 4;
+		unsigned long mic : 4;
+		unsigned long rsv : 8;
+		unsigned long mmi : 1;
+		unsigned long ig1 : 47;
+	};
+} ia64_tpr;
+
+typedef union {
+	unsigned long val;
+	struct {
+		unsigned long rv3  :  2; /* 0-1 */
+		unsigned long ps   :  6; /* 2-7 */
+		unsigned long key  : 24; /* 8-31 */
+		unsigned long rv4  : 32; /* 32-63 */
+	};
+} ia64_itir;
+
+typedef union {
+	unsigned long val;
+	struct {
+		unsigned long  ve		:  1;  /* enable hw walker */
+		unsigned long  reserved0 :  1;  /* reserved */
+		unsigned long  ps		:  6;  /* log page size */
+		unsigned long  rid	   : 24;  /* region id */
+		unsigned long  reserved1 : 32;  /* reserved */
+	};
+} ia64_rr;
+
+typedef union {
+	__u64 val;
+	struct {
+		__u64 ig0 : 4;
+		__u64 mic : 4;
+		__u64 rsv : 8;
+		__u64 mmi : 1;
+		__u64 ig1 : 47;
+	};
+} tpr_t;
+
+/*
+ region register macros
+*/
+#define RR_TO_VE(arg)   (((arg) >> 0) & 0x0000000000000001)
+#define RR_VE(arg)	  (((arg) & 0x0000000000000001) << 0)
+#define RR_VE_MASK	  0x0000000000000001L
+#define RR_VE_SHIFT	 0
+#define RR_TO_PS(arg)   (((arg) >> 2) & 0x000000000000003f)
+#define RR_PS(arg)	  (((arg) & 0x000000000000003f) << 2)
+#define RR_PS_MASK	  0x00000000000000fcL
+#define RR_PS_SHIFT	 2
+#define RR_TO_RID(arg)  (((arg) >> 8) & 0x0000000000ffffff)
+#define RR_RID_MASK	 0x00000000ffffff00L
+
+#define IA64_FIRST_STACKED_GR   32
+#define IA64_FIRST_ROTATING_FR  32
+
+/* Generate Mask
+ * Parameter:
+ *  bit -- starting bit
+ *  len -- how many bits
+ */
+#define MASK(bit,len)				   	\
+({							\
+		__u64	ret;				\
+							\
+		__asm __volatile("dep %0=-1, r0, %1, %2"\
+				: "=r" (ret):		\
+		  "M" (bit),				\
+		  "M" (len));				\
+		ret;					\
+})
+
+/*
+ * Flushrs instruction stream.
+ */
+#define ia64_flushrs() asm volatile ("flushrs;;":::"memory")
+
+#define ia64_loadrs() asm volatile ("loadrs;;":::"memory")
+
+#define ia64_get_rsc()							\
+({									\
+	unsigned long val;						\
+	asm volatile ("mov %0=ar.rsc;;" : "=r"(val) :: "memory");	\
+	val;								\
+})
+
+#define ia64_set_rsc(val)					\
+	asm volatile ("mov ar.rsc=%0;;" :: "r"(val) : "memory")
+
+#define ia64_get_bspstore()	 					\
+({									\
+	unsigned long val;						\
+	asm volatile ("mov %0=ar.bspstore;;" : "=r"(val) :: "memory");	\
+	val;								\
+})
+
+#define ia64_set_bspstore(val)					   \
+	asm volatile ("mov ar.bspstore=%0;;" :: "r"(val) : "memory")
+
+#define ia64_get_rnat()	 						\
+({									\
+	unsigned long val;						\
+	asm volatile ("mov %0=ar.rnat;" : "=r"(val) :: "memory");	\
+	val;								\
+})
+
+#define ia64_set_rnat(val)					\
+	asm volatile ("mov ar.rnat=%0;;" :: "r"(val) : "memory")
+
+static inline unsigned long ia64_get_itc(void)
+{
+	unsigned long result;
+	result = ia64_getreg(_IA64_REG_AR_ITC);
+	return result;
+}
+
+static inline void ia64_set_dcr(unsigned long dcr)
+{
+	ia64_setreg(_IA64_REG_CR_DCR, dcr);
+}
+
+#define ia64_ttag(addr)							\
+({									  \
+	__u64 ia64_intri_res;						   \
+	asm volatile ("ttag %0=%1" : "=r"(ia64_intri_res) : "r" (addr));   \
+	ia64_intri_res;							 \
+})
+
+static inline unsigned long
+rotate_reg(unsigned long sor, unsigned long rrb, unsigned long reg)
+{
+	reg += rrb;
+	if (reg >= sor)
+		reg -= sor;
+	return reg;
+}
+#endif
+
+#endif /* _KVM_ASM_IA64_PROCESSOR_H */
diff --git a/arch/ia64/kvm/kvm_minstate.h b/arch/ia64/kvm/kvm_minstate.h
new file mode 100644
index 0000000..dace5fa
--- /dev/null
+++ b/arch/ia64/kvm/kvm_minstate.h
@@ -0,0 +1,273 @@
+/*
+ *  kvm_minstate.h: min save macros 
+ *  Copyright (c) 2007, Intel Corporation.
+ *
+ *  Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
+ *  Xiantao Zhang (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+
+#include <asm/asmmacro.h>
+#include <asm/types.h>
+#include <asm/kregs.h>
+#include "asm-offsets.h"
+
+#define KVM_MINSTATE_START_SAVE_MIN	     					\
+	mov ar.rsc=0;/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */\
+	;;									\
+	mov.m r28=ar.rnat;                                  			\
+	addl r22=VMM_RBS_OFFSET,r1;            /* compute base of RBS */	\
+	;;									\
+	lfetch.fault.excl.nt1 [r22];						\
+	addl r1=IA64_STK_OFFSET-VMM_PT_REGS_SIZE,r1;  /* compute base of memory stack */  \
+	mov r23=ar.bspstore;			/* save ar.bspstore */          \
+	;;									\
+	mov ar.bspstore=r22;				/* switch to kernel RBS */\
+	;;									\
+	mov r18=ar.bsp;								\
+	mov ar.rsc=0x3;     /* set eager mode, pl 0, little-endian, loadrs=0 */	
+
+
+
+#define KVM_MINSTATE_END_SAVE_MIN						\
+	bsw.1;          /* switch back to bank 1 (must be last in insn group) */\
+	;;
+
+
+#define PAL_VSA_SYNC_READ						\
+	/* begin to call pal vps sync_read */				\
+	add r25=VMM_VPD_BASE_OFFSET, r21;				\
+	adds r20=VMM_VCPU_VSA_BASE_OFFSET, r21;  /* entry point */	\
+	;;								\
+	ld8 r25=[r25];      /* read vpd base */				\
+	ld8 r20=[r20];							\
+	;;								\
+	add r20=PAL_VPS_SYNC_READ,r20;					\
+	;;								\
+{ .mii;									\
+	nop 0x0;							\
+	mov r24=ip;							\
+	mov b0=r20;							\
+	;;								\
+};									\
+{ .mmb;									\
+	add r24 = 0x20, r24;						\
+	nop 0x0;							\
+	br.cond.sptk b0;        /*  call the service */			\
+	;;								\
+};
+
+
+
+#define KVM_MINSTATE_GET_CURRENT(reg)   mov reg=r21
+
+/*
+ * KVM_DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
+ * the minimum state necessary that allows us to turn psr.ic back
+ * on.
+ *
+ * Assumed state upon entry:
+ *  psr.ic: off
+ *  r31:	contains saved predicates (pr)
+ *
+ * Upon exit, the state is as follows:
+ *  psr.ic: off
+ *   r2 = points to &pt_regs.r16
+ *   r8 = contents of ar.ccv
+ *   r9 = contents of ar.csd
+ *  r10 = contents of ar.ssd
+ *  r11 = FPSR_DEFAULT
+ *  r12 = kernel sp (kernel virtual address)
+ *  r13 = points to current task_struct (kernel virtual address)
+ *  p15 = TRUE if psr.i is set in cr.ipsr
+ *  predicate registers (other than p2, p3, and p15), b6, r3, r14, r15:
+ *	  preserved
+ *
+ * Note that psr.ic is NOT turned on by this macro.  This is so that
+ * we can pass interruption state as arguments to a handler.
+ */
+
+
+#define PT(f) (VMM_PT_REGS_##f##_OFFSET)
+
+#define KVM_DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA)			\
+	KVM_MINSTATE_GET_CURRENT(r16);  /* M (or M;;I) */	\
+	mov r27=ar.rsc;         /* M */				\
+	mov r20=r1;         /* A */				\
+	mov r25=ar.unat;        /* M */				\
+	mov r29=cr.ipsr;        /* M */				\
+	mov r26=ar.pfs;         /* I */				\
+	mov r18=cr.isr;         				\
+	COVER;              /* B;; (or nothing) */		\
+	;;							\
+	tbit.z p0,p15=r29,IA64_PSR_I_BIT;			\
+	mov r1=r16;						\
+/*	mov r21=r16;	*/					\
+	/* switch from user to kernel RBS: */			\
+	;;							\
+	invala;             /* M */				\
+	SAVE_IFS;						\
+	;;							\
+	KVM_MINSTATE_START_SAVE_MIN				\
+	adds r17=2*L1_CACHE_BYTES,r1;/* cache-line size */	\
+	adds r16=PT(CR_IPSR),r1;				\
+	;;							\
+	lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES;		\
+	st8 [r16]=r29;      /* save cr.ipsr */			\
+	;;							\
+	lfetch.fault.excl.nt1 [r17];				\
+	tbit.nz p15,p0=r29,IA64_PSR_I_BIT;			\
+	mov r29=b0						\
+	;;							\
+	adds r16=PT(R8),r1; /* initialize first base pointer */	\
+	adds r17=PT(R9),r1; /* initialize second base pointer */\
+	;;							\
+.mem.offset 0,0; st8.spill [r16]=r8,16;				\
+.mem.offset 8,0; st8.spill [r17]=r9,16;				\
+	;;							\
+.mem.offset 0,0; st8.spill [r16]=r10,24;			\
+.mem.offset 8,0; st8.spill [r17]=r11,24;			\
+	;;							\
+	mov r9=cr.iip;         /* M */				\
+	mov r10=ar.fpsr;        /* M */				\
+	;;							\
+	st8 [r16]=r9,16;    /* save cr.iip */			\
+	st8 [r17]=r30,16;   /* save cr.ifs */			\
+	sub r18=r18,r22;    /* r18=RSE.ndirty*8 */		\
+	;;							\
+	st8 [r16]=r25,16;   /* save ar.unat */			\
+	st8 [r17]=r26,16;    /* save ar.pfs */			\
+	shl r18=r18,16;     /* calu ar.rsc used for "loadrs" */	\
+	;;							\
+	st8 [r16]=r27,16;   /* save ar.rsc */			\
+	st8 [r17]=r28,16;   /* save ar.rnat */			\
+	;;          /* avoid RAW on r16 & r17 */		\
+	st8 [r16]=r23,16;   /* save ar.bspstore */		\
+	st8 [r17]=r31,16;   /* save predicates */		\
+	;;							\
+	st8 [r16]=r29,16;   /* save b0 */			\
+	st8 [r17]=r18,16;   /* save ar.rsc value for "loadrs" */\
+	;;							\
+.mem.offset 0,0; st8.spill [r16]=r20,16;/* save original r1 */  \
+.mem.offset 8,0; st8.spill [r17]=r12,16;			\
+	adds r12=-16,r1;    /* switch to kernel memory stack (with 16 bytes of scratch) */  \
+	;;							\
+.mem.offset 0,0; st8.spill [r16]=r13,16;			\
+.mem.offset 8,0; st8.spill [r17]=r10,16;	/* save ar.fpsr */\
+	mov r13=r21;   /* establish `current' */		\
+	;;							\
+.mem.offset 0,0; st8.spill [r16]=r15,16;			\
+.mem.offset 8,0; st8.spill [r17]=r14,16;			\
+	;;							\
+.mem.offset 0,0; st8.spill [r16]=r2,16;				\
+.mem.offset 8,0; st8.spill [r17]=r3,16;				\
+	adds r2=VMM_PT_REGS_R16_OFFSET,r1;			\
+	 ;;							\
+	adds r16=VMM_VCPU_IIPA_OFFSET,r13;			\
+	adds r17=VMM_VCPU_ISR_OFFSET,r13;			\
+	mov r26=cr.iipa;					\
+	mov r27=cr.isr;						\
+	;;							\
+	st8 [r16]=r26;						\
+	st8 [r17]=r27;						\
+	;;							\
+	EXTRA;							\
+	mov r8=ar.ccv;						\
+	mov r9=ar.csd;						\
+	mov r10=ar.ssd;						\
+	movl r11=FPSR_DEFAULT;   /* L-unit */			\
+	adds r17=VMM_VCPU_GP_OFFSET,r13;			\
+	;;							\
+	ld8 r1=[r17];/* establish kernel global pointer */	\
+	;;							\
+	PAL_VSA_SYNC_READ					\
+	KVM_MINSTATE_END_SAVE_MIN
+
+/*
+ * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
+ *
+ * Assumed state upon entry:
+ *  psr.ic: on
+ *  r2: points to &pt_regs.f6
+ *  r3: points to &pt_regs.f7
+ *  r8: contents of ar.ccv
+ *  r9: contents of ar.csd
+ *  r10:	contents of ar.ssd
+ *  r11:	FPSR_DEFAULT
+ *
+ * Registers r14 and r15 are guaranteed not to be touched by SAVE_REST.
+ */
+#define KVM_SAVE_REST			\
+.mem.offset 0,0; st8.spill [r2]=r16,16;	\
+.mem.offset 8,0; st8.spill [r3]=r17,16;	\
+	;;				\
+.mem.offset 0,0; st8.spill [r2]=r18,16;	\
+.mem.offset 8,0; st8.spill [r3]=r19,16;	\
+	;;				\
+.mem.offset 0,0; st8.spill [r2]=r20,16;	\
+.mem.offset 8,0; st8.spill [r3]=r21,16;	\
+	mov r18=b6;			\
+	;;				\
+.mem.offset 0,0; st8.spill [r2]=r22,16;	\
+.mem.offset 8,0; st8.spill [r3]=r23,16;	\
+	mov r19=b7;			\
+	;;				\
+.mem.offset 0,0; st8.spill [r2]=r24,16;	\
+.mem.offset 8,0; st8.spill [r3]=r25,16;	\
+	;;				\
+.mem.offset 0,0; st8.spill [r2]=r26,16;	\
+.mem.offset 8,0; st8.spill [r3]=r27,16;	\
+	;;				\
+.mem.offset 0,0; st8.spill [r2]=r28,16;	\
+.mem.offset 8,0; st8.spill [r3]=r29,16;	\
+	;;				\
+.mem.offset 0,0; st8.spill [r2]=r30,16;	\
+.mem.offset 8,0; st8.spill [r3]=r31,32;	\
+	;;				\
+	mov ar.fpsr=r11;		\
+	st8 [r2]=r8,8;			\
+	adds r24=PT(B6)-PT(F7),r3;	\
+	adds r25=PT(B7)-PT(F7),r3;	\
+	;;				\
+	st8 [r24]=r18,16;       /* b6 */\
+	st8 [r25]=r19,16;       /* b7 */\
+	adds r2=PT(R4)-PT(F6),r2;	\
+	adds r3=PT(R5)-PT(F7),r3;	\
+	;;				\
+	st8 [r24]=r9;	/* ar.csd */	\
+	st8 [r25]=r10;	/* ar.ssd */	\
+	;;				\
+	mov r18=ar.unat;		\
+	adds r19=PT(EML_UNAT)-PT(R4),r2;\
+	;;				\
+	st8 [r19]=r18; /* eml_unat */ 	\
+
+
+#define KVM_SAVE_EXTRA			\
+.mem.offset 0,0; st8.spill [r2]=r4,16;	\
+.mem.offset 8,0; st8.spill [r3]=r5,16;	\
+	;;				\
+.mem.offset 0,0; st8.spill [r2]=r6,16;	\
+.mem.offset 8,0; st8.spill [r3]=r7;	\
+	;;				\
+	mov r26=ar.unat;		\
+	;;				\
+	st8 [r2]=r26;/* eml_unat */ 	\
+
+#define KVM_SAVE_MIN_WITH_COVER		KVM_DO_SAVE_MIN(cover, mov r30=cr.ifs,)
+#define KVM_SAVE_MIN_WITH_COVER_R19	KVM_DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19)
+#define KVM_SAVE_MIN			KVM_DO_SAVE_MIN(     , mov r30=r0, )
diff --git a/arch/ia64/kvm/lapic.h b/arch/ia64/kvm/lapic.h
new file mode 100644
index 0000000..8c2280a
--- /dev/null
+++ b/arch/ia64/kvm/lapic.h
@@ -0,0 +1,27 @@
+#ifndef __KVM_IA64_LAPIC_H
+#define __KVM_IA64_LAPIC_H
+
+#include "iodev.h"
+
+#include <linux/kvm_host.h>
+
+/*
+ * vlsapic
+ */
+struct kvm_lapic{
+    uint64_t insvc[4];
+    uint64_t vhpi;
+    uint8_t xtp;
+    uint8_t pal_init_pending;
+    uint8_t pad[2];
+};
+
+
+int kvm_create_lapic(struct kvm_vcpu *vcpu);
+void kvm_free_lapic(struct kvm_vcpu *vcpu);
+
+int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
+int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
+int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig);
+
+#endif
diff --git a/arch/ia64/kvm/misc.h b/arch/ia64/kvm/misc.h
new file mode 100644
index 0000000..aa2428b
--- /dev/null
+++ b/arch/ia64/kvm/misc.h
@@ -0,0 +1,95 @@
+#ifndef __KVM_IA64_MISC_H
+#define __KVM_IA64_MISC_H
+
+#include <linux/kvm_host.h>
+/*
+ * misc.h
+ * 	Copyright (C) 2007, Intel Corporation.
+ *  	Xiantao Zhang  (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+/*
+ *Return p2m base address at host side!
+ */
+static inline uint64_t *kvm_host_get_pmt(struct kvm *kvm)
+{
+	return (uint64_t *)(kvm->arch.vm_base + KVM_P2M_OFS);
+}
+
+static inline void kvm_set_pmt_entry(struct kvm *kvm, gfn_t gfn,
+		u64 paddr, u64 mem_flags)
+{
+	uint64_t *pmt_base = kvm_host_get_pmt(kvm);
+	unsigned long pte;
+
+	pte = PAGE_ALIGN(paddr) | mem_flags;
+	pmt_base[gfn] = pte;
+}
+
+/*Function for translating host address to guest address*/
+
+static inline void *to_guest(struct kvm *kvm, void *addr)
+{
+	return (void *)((unsigned long)(addr) - kvm->arch.vm_base +
+			KVM_VM_DATA_BASE);
+}
+
+/*function for translating guest address to host address*/
+
+static inline void *to_host(struct kvm *kvm, void *addr)
+{
+	return (void *)((unsigned long)addr - KVM_VM_DATA_BASE
+			+ kvm->arch.vm_base);
+}
+
+/* Get host context of the vcpu */
+static inline context_t *kvm_get_host_context(struct kvm_vcpu *vcpu)
+{
+	context_t *ctx = &vcpu->arch.host;
+	return to_guest(vcpu->kvm, ctx);
+}
+
+/* Get guest context of the vcpu */
+static inline context_t *kvm_get_guest_context(struct kvm_vcpu *vcpu)
+{
+	context_t *ctx = &vcpu->arch.guest;
+	return  to_guest(vcpu->kvm, ctx);
+}
+
+/* kvm get exit data from gvmm! */
+static inline struct exit_ctl_data *kvm_get_exit_data(struct kvm_vcpu *vcpu)
+{
+	return &vcpu->arch.exit_data;
+}
+
+/*kvm get vcpu ioreq for kvm module!*/
+static inline ioreq_t *kvm_get_vcpu_ioreq(struct kvm_vcpu *vcpu)
+{
+	struct exit_ctl_data *p_ctl_data;
+
+	if (vcpu) {
+		p_ctl_data = kvm_get_exit_data(vcpu);
+		if (p_ctl_data->exit_reason == EXIT_REASON_MMIO_INSTRUCTION
+				|| p_ctl_data->exit_reason ==
+						EXIT_REASON_IO_INSTRUCTION)
+			return &p_ctl_data->u.ioreq;
+	}
+
+	return NULL;
+}
+
+#endif
diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h
new file mode 100644
index 0000000..f87dd8c
--- /dev/null
+++ b/arch/ia64/kvm/vcpu.h
@@ -0,0 +1,807 @@
+/*
+ *  vcpu.h: vcpu routines
+ *  	Copyright (c) 2005, Intel Corporation.
+ *  	Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
+ *  	Yaozu Dong (Eddie Dong) (Eddie.dong@intel.com)
+ *
+ * 	Copyright (c) 2007, Intel Corporation.
+ *  	Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
+ *	Xiantao Zhang (xiantao.zhang@intel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+
+#ifndef __KVM_VCPU_H__
+#define __KVM_VCPU_H__
+
+#include <asm/types.h>
+#include <asm/fpu.h>
+#include <asm/processor.h>
+
+#ifndef __ASSEMBLY__
+#include "vti.h"
+#include "ia64_regs.h"
+
+#include <linux/kvm_host.h>
+
+typedef unsigned long IA64_INST;
+
+typedef union U_IA64_BUNDLE {
+    unsigned long i64[2];
+    struct { unsigned long template:5, slot0:41, slot1a:18,
+						slot1b:23, slot2:41; };
+	/* NOTE: following doesn't work because bitfields can't cross natural
+	size boundaries
+	struct { unsigned long template:5, slot0:41, slot1:41, slot2:41; }; */
+} IA64_BUNDLE;
+
+typedef enum E_IA64_SLOT_TYPE {I, M, F, B, L, ILLEGAL} IA64_SLOT_TYPE;
+
+typedef union U_INST64_A5 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, imm7b:7, r3:2, imm5c:5,
+						imm9d:9, s:1, major:4; };
+} INST64_A5;
+
+typedef union U_INST64_B4 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, btype:3, un3:3, p:1, b2:3, un11:11, x6:6,
+			wh:2, d:1, un1:1, major:4; };
+} INST64_B4;
+
+typedef union U_INST64_B8 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, un21:21, x6:6, un4:4, major:4; };
+} INST64_B8;
+
+typedef union U_INST64_B9 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, imm20:20, :1, x6:6, :3, i:1, major:4; };
+} INST64_B9;
+
+typedef union U_INST64_I19 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, imm20:20, :1, x6:6, x3:3, i:1, major:4; };
+} INST64_I19;
+
+typedef union U_INST64_I26 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, r2:7, ar3:7, x6:6, x3:3, :1, major:4; };
+} INST64_I26;
+
+typedef union U_INST64_I27 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, imm:7, ar3:7, x6:6, x3:3, s:1, major:4; };
+} INST64_I27;
+
+typedef union U_INST64_I28 { /* not privileged (mov from AR) */
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, :7, ar3:7, x6:6, x3:3, :1, major:4; };
+} INST64_I28;
+
+typedef union U_INST64_M28 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :14, r3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M28;
+
+typedef union U_INST64_M29 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, r2:7, ar3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M29;
+
+typedef union U_INST64_M30 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, imm:7, ar3:7, x4:4, x2:2,
+							x3:3, s:1, major:4; };
+} INST64_M30;
+
+typedef union U_INST64_M31 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, :7, ar3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M31;
+
+typedef union U_INST64_M32 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, r2:7, cr3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M32;
+
+typedef union U_INST64_M33 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, :7, cr3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M33;
+
+typedef union U_INST64_M35 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, r2:7, :7, x6:6, x3:3, :1, major:4; };
+
+} INST64_M35;
+
+typedef union U_INST64_M36 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, :14, x6:6, x3:3, :1, major:4; };
+} INST64_M36;
+
+typedef union U_INST64_M37 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, imm20a:20, :1, x4:4, x2:2, x3:3,
+					i:1, major:4; };
+} INST64_M37;
+
+typedef union U_INST64_M41 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, r2:7, :7, x6:6, x3:3, :1, major:4; };
+} INST64_M41;
+
+typedef union U_INST64_M42 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, r2:7, r3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M42;
+
+typedef union U_INST64_M43 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, :7, r3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M43;
+
+typedef union U_INST64_M44 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, imm:21, x4:4, i2:2, x3:3, i:1, major:4; };
+} INST64_M44;
+
+typedef union U_INST64_M45 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, r2:7, r3:7, x6:6, x3:3, :1, major:4; };
+} INST64_M45;
+
+typedef union U_INST64_M46 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, un7:7, r3:7, x6:6,
+					x3:3, un1:1, major:4; };
+} INST64_M46;
+
+typedef union U_INST64_M47 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, un14:14, r3:7, x6:6, x3:3, un1:1, major:4; };
+} INST64_M47;
+
+typedef union U_INST64_M1{
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, un7:7, r3:7, x:1, hint:2,
+							x6:6, m:1, major:4; };
+} INST64_M1;
+
+typedef union U_INST64_M2{
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, r2:7, r3:7, x:1, hint:2,
+							x6:6, m:1, major:4; };
+} INST64_M2;
+
+typedef union U_INST64_M3{
+    IA64_INST inst;
+    struct { unsigned long qp:6, r1:7, imm7:7, r3:7, i:1, hint:2,
+					x6:6, s:1, major:4; };
+} INST64_M3;
+
+typedef union U_INST64_M4 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, un7:7, r2:7, r3:7, x:1, hint:2,
+						x6:6, m:1, major:4; };
+} INST64_M4;
+
+typedef union U_INST64_M5 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, imm7:7, r2:7, r3:7, i:1, hint:2,
+						x6:6, s:1, major:4; };
+} INST64_M5;
+
+typedef union U_INST64_M6 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, f1:7, un7:7, r3:7, x:1, hint:2,
+						x6:6, m:1, major:4; };
+} INST64_M6;
+
+typedef union U_INST64_M9 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, f2:7, r3:7, x:1, hint:2,
+						x6:6, m:1, major:4; };
+} INST64_M9;
+
+typedef union U_INST64_M10 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, imm7:7, f2:7, r3:7, i:1, hint:2,
+						x6:6, s:1, major:4; };
+} INST64_M10;
+
+typedef union U_INST64_M12 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, f1:7, f2:7, r3:7, x:1, hint:2,
+						x6:6, m:1, major:4; };
+} INST64_M12;
+
+typedef union U_INST64_M15 {
+    IA64_INST inst;
+    struct { unsigned long qp:6, :7, imm7:7, r3:7, i:1, hint:2,
+						x6:6, s:1, major:4; };
+} INST64_M15;
+
+typedef union U_INST64 {
+    IA64_INST inst;
+    struct { unsigned long :37, major:4; } generic;
+    INST64_A5 A5;	/* used in build_hypercall_bundle only */
+    INST64_B4 B4;	/* used in build_hypercall_bundle only */
+    INST64_B8 B8;	/* rfi, bsw.[01] */
+    INST64_B9 B9;	/* break.b */
+    INST64_I19 I19;	/* used in build_hypercall_bundle only */
+    INST64_I26 I26;	/* mov register to ar (I unit) */
+    INST64_I27 I27;	/* mov immediate to ar (I unit) */
+    INST64_I28 I28;	/* mov from ar (I unit) */
+    INST64_M1  M1;	/* ld integer */
+    INST64_M2  M2;
+    INST64_M3  M3;
+    INST64_M4  M4;	/* st integer */
+    INST64_M5  M5;
+    INST64_M6  M6;	/* ldfd floating pointer 		*/
+    INST64_M9  M9;	/* stfd floating pointer		*/
+    INST64_M10 M10;	/* stfd floating pointer		*/
+    INST64_M12 M12;     /* ldfd pair floating pointer		*/
+    INST64_M15 M15;	/* lfetch + imm update			*/
+    INST64_M28 M28;	/* purge translation cache entry	*/
+    INST64_M29 M29;	/* mov register to ar (M unit)		*/
+    INST64_M30 M30;	/* mov immediate to ar (M unit)		*/
+    INST64_M31 M31;	/* mov from ar (M unit)			*/
+    INST64_M32 M32;	/* mov reg to cr			*/
+    INST64_M33 M33;	/* mov from cr				*/
+    INST64_M35 M35;	/* mov to psr				*/
+    INST64_M36 M36;	/* mov from psr				*/
+    INST64_M37 M37;	/* break.m				*/
+    INST64_M41 M41;	/* translation cache insert		*/
+    INST64_M42 M42;	/* mov to indirect reg/translation reg insert*/
+    INST64_M43 M43;	/* mov from indirect reg		*/
+    INST64_M44 M44;	/* set/reset system mask		*/
+    INST64_M45 M45;	/* translation purge			*/
+    INST64_M46 M46;	/* translation access (tpa,tak)		*/
+    INST64_M47 M47;	/* purge translation entry		*/
+} INST64;
+
+#define MASK_41 ((unsigned long)0x1ffffffffff)
+
+struct kvm_pt_regs {
+    /* The following registers are saved by SAVE_MIN: */
+    unsigned long b6;  /* scratch */
+    unsigned long b7;  /* scratch */
+
+    unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */
+    unsigned long ar_ssd; /* reserved for future use (scratch) */
+
+    unsigned long r8;  /* scratch (return value register 0) */
+    unsigned long r9;  /* scratch (return value register 1) */
+    unsigned long r10; /* scratch (return value register 2) */
+    unsigned long r11; /* scratch (return value register 3) */
+
+    unsigned long cr_ipsr; /* interrupted task's psr */
+    unsigned long cr_iip;  /* interrupted task's instruction pointer */
+    unsigned long cr_ifs;  /* interrupted task's function state */
+
+    unsigned long ar_unat; /* interrupted task's NaT register (preserved) */
+    unsigned long ar_pfs;  /* prev function state  */
+    unsigned long ar_rsc;  /* RSE configuration */
+    /* The following two are valid only if cr_ipsr.cpl > 0: */
+    unsigned long ar_rnat;  /* RSE NaT */
+    unsigned long ar_bspstore; /* RSE bspstore */
+
+    unsigned long pr;  /* 64 predicate registers (1 bit each) */
+    unsigned long b0;  /* return pointer (bp) */
+    unsigned long loadrs;  /* size of dirty partition << 16 */
+
+    unsigned long r1;  /* the gp pointer */
+    unsigned long r12; /* interrupted task's memory stack pointer */
+    unsigned long r13; /* thread pointer */
+
+    unsigned long ar_fpsr;  /* floating point status (preserved) */
+    unsigned long r15;  /* scratch */
+
+ /* The remaining registers are NOT saved for system calls.  */
+
+    unsigned long r14;  /* scratch */
+    unsigned long r2;  /* scratch */
+    unsigned long r3;  /* scratch */
+    unsigned long r16;  /* scratch */
+    unsigned long r17;  /* scratch */
+    unsigned long r18;  /* scratch */
+    unsigned long r19;  /* scratch */
+    unsigned long r20;  /* scratch */
+    unsigned long r21;  /* scratch */
+    unsigned long r22;  /* scratch */
+    unsigned long r23;  /* scratch */
+    unsigned long r24;  /* scratch */
+    unsigned long r25;  /* scratch */
+    unsigned long r26;  /* scratch */
+    unsigned long r27;  /* scratch */
+    unsigned long r28;  /* scratch */
+    unsigned long r29;  /* scratch */
+    unsigned long r30;  /* scratch */
+    unsigned long r31;  /* scratch */
+    unsigned long ar_ccv;  /* compare/exchange value (scratch) */
+
+
+    /*
+     * Floating point registers that the kernel considers scratch:
+     */
+    struct ia64_fpreg f6;  /* scratch */
+    struct ia64_fpreg f7;  /* scratch */
+    struct ia64_fpreg f8;  /* scratch */
+    struct ia64_fpreg f9;  /* scratch */
+    struct ia64_fpreg f10;  /* scratch */
+    struct ia64_fpreg f11;  /* scratch */
+
+    unsigned long r4;  /* preserved */
+    unsigned long r5;  /* preserved */
+    unsigned long r6;  /* preserved */
+    unsigned long r7;  /* preserved */
+    unsigned long eml_unat;    /* used for emulating instruction */
+    unsigned long pad0;     /* alignment pad */
+
+};
+
+/* Virtual address memory attributes encoding */
+#define VA_MATTR_WB         0x0
+#define VA_MATTR_UC         0x4
+#define VA_MATTR_UCE        0x5
+#define VA_MATTR_WC         0x6
+#define VA_MATTR_NATPAGE    0x7
+
+#define PMASK(size)         (~((size) - 1))
+#define PSIZE(size)         (1UL<<(size))
+#define CLEARLSB(ppn, nbits)    (((ppn) >> (nbits)) << (nbits))
+#define PAGEALIGN(va, ps)	CLEARLSB(va, ps)
+#define PAGE_FLAGS_RV_MASK   (0x2|(0x3UL<<50)|(((1UL<<11)-1)<<53))
+#define _PAGE_MA_ST     (0x1 <<  2) /* is reserved for software use */
+
+#define ARCH_PAGE_SHIFT   12
+
+#define INVALID_TI_TAG (1UL << 63)
+
+#define VTLB_PTE_P_BIT      0
+#define VTLB_PTE_IO_BIT     60
+#define VTLB_PTE_IO         (1UL<<VTLB_PTE_IO_BIT)
+#define VTLB_PTE_P          (1UL<<VTLB_PTE_P_BIT)
+
+
+#define vcpu_quick_region_check(_tr_regions,_ifa)		\
+	(_tr_regions & (1 << ((unsigned long)_ifa >> 61)))
+
+#define vcpu_quick_region_set(_tr_regions,_ifa)             \
+	do {_tr_regions |= (1 << ((unsigned long)_ifa >> 61)); } while (0)
+
+
+static inline void vcpu_set_tr(thash_data_t *trp, u64 pte, u64 itir,
+					u64 va, u64 rid)
+{
+	trp->page_flags = pte;
+	trp->itir = itir;
+	trp->vadr = va;
+	trp->rid = rid;
+}
+
+
+extern u64 kvm_lookup_mpa(u64 gpfn);
+extern u64 kvm_gpa_to_mpa(u64 gpa);
+
+/* Return I/O type if trye */
+#define __gpfn_is_io(gpfn)			\
+    ({						\
+	u64 pte, ret = 0;			\
+	pte = kvm_lookup_mpa(gpfn);		\
+	if (!(pte & GPFN_INV_MASK))		\
+		ret = pte & GPFN_IO_MASK;	\
+	ret;					\
+     })
+
+#endif
+
+#define IA64_NO_FAULT	0
+#define IA64_FAULT	1
+
+#define VMM_RBS_OFFSET  ((VMM_TASK_SIZE + 15) & ~15)
+
+#define SW_BAD  0   /* Bad mode transitition */
+#define SW_V2P  1   /* Physical emulatino is activated */
+#define SW_P2V  2   /* Exit physical mode emulation */
+#define SW_SELF 3   /* No mode transition */
+#define SW_NOP  4   /* Mode transition, but without action required */
+
+#define GUEST_IN_PHY    0x1
+#define GUEST_PHY_EMUL  0x2
+
+#define current_vcpu ((struct kvm_vcpu *) ia64_getreg(_IA64_REG_TP))
+
+#define VRN_SHIFT	61
+#define VRN_MASK	0xe000000000000000
+#define VRN0		0x0UL
+#define VRN1		0x1UL
+#define VRN2		0x2UL
+#define VRN3		0x3UL
+#define VRN4		0x4UL
+#define VRN5		0x5UL
+#define VRN6		0x6UL
+#define VRN7		0x7UL
+
+#define IRQ_NO_MASKED         0
+#define IRQ_MASKED_BY_VTPR    1
+#define IRQ_MASKED_BY_INSVC   2   /* masked by inservice IRQ */
+
+#define PTA_BASE_SHIFT      15
+
+#define IA64_PSR_VM_BIT     46
+#define IA64_PSR_VM (__IA64_UL(1) << IA64_PSR_VM_BIT)
+
+/* Interruption Function State */
+#define IA64_IFS_V_BIT      63
+#define IA64_IFS_V  (__IA64_UL(1) << IA64_IFS_V_BIT)
+
+#define PHY_PAGE_UC (_PAGE_A|_PAGE_D|_PAGE_P|_PAGE_MA_UC|_PAGE_AR_RWX)
+#define PHY_PAGE_WB (_PAGE_A|_PAGE_D|_PAGE_P|_PAGE_MA_WB|_PAGE_AR_RWX)
+
+#ifndef __ASSEMBLY__
+
+#include <asm/kvm_host.h>
+#include <asm/gcc_intrin.h>
+
+#define is_physical_mode(v)		\
+	((v->arch.mode_flags) & GUEST_IN_PHY)
+
+#define is_virtual_mode(v)	\
+	(!is_physical_mode(v))
+
+#define MODE_IND(psr)	\
+	(((psr).it << 2) + ((psr).dt << 1) + (psr).rt)
+
+enum {
+	I_TLB = 1,
+	D_TLB = 2
+};
+
+typedef union kvm_va {
+	struct {
+		unsigned long off : 60;		/* intra-region offset */
+		unsigned long reg :  4;		/* region number */
+	} f;
+	unsigned long l;
+	void *p;
+} kvm_va;
+
+#define __kvm_pa(x)     ({kvm_va _v; _v.l = (long) (x); _v.f.reg = 0; _v.l; })
+#define __kvm_va(x)     ({kvm_va _v; _v.l = (long) (x); _v.f.reg = -1; _v.p; })
+
+#define _REGION_ID(x)           ({ia64_rr _v; _v.val = (long)(x); _v.rid; })
+#define _REGION_PAGE_SIZE(x)    ({ia64_rr _v; _v.val = (long)(x); _v.ps; })
+#define _REGION_HW_WALKER(x)    ({ia64_rr _v; _v.val = (long)(x); _v.ve; })
+
+
+typedef struct kvm_vcpu VCPU;
+typedef struct kvm_pt_regs REGS;
+typedef enum { DATA_REF, NA_REF, INST_REF, RSE_REF } vhpt_ref_t;
+typedef enum { INSTRUCTION, DATA, REGISTER } miss_type;
+
+#define VCPU(_v, _x) ((_v)->arch.vpd->_x)
+#define VMX(_v, _x)  ((_v)->arch._x)
+
+#define VLSAPIC_INSVC(vcpu, i) ((vcpu)->arch.insvc[i])
+#define VLSAPIC_XTP(_v)        VMX(_v, xtp)
+
+	static inline struct kvm_pt_regs *
+vcpu_regs(VCPU *v)
+{
+	return (struct kvm_pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
+}
+
+
+static inline unsigned long itir_ps(unsigned long itir)
+{
+	return ((itir >> 2) & 0x3f);
+}
+
+
+/**************************************************************************
+  VCPU control register access routines
+ **************************************************************************/
+static inline u64 vcpu_get_itir(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, itir));
+}
+
+static inline void vcpu_set_itir(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, itir) = val;
+}
+
+static inline u64 vcpu_get_ifa(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, ifa));
+}
+
+static inline void vcpu_set_ifa(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, ifa) = val;
+}
+
+static inline u64 vcpu_get_iva(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, iva));
+}
+
+static inline u64 vcpu_get_pta(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, pta));
+}
+
+static inline u64 vcpu_get_lid(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, lid));
+}
+
+static inline u64 vcpu_get_tpr(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, tpr));
+}
+
+static inline u64 vcpu_get_eoi(VCPU *vcpu)
+{
+	return (0UL);		/*reads of eoi always return 0 */
+}
+
+static inline u64 vcpu_get_irr0(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, irr[0]));
+}
+
+static inline u64 vcpu_get_irr1(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, irr[1]));
+}
+
+static inline u64 vcpu_get_irr2(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, irr[2]));
+}
+
+static inline u64 vcpu_get_irr3(VCPU *vcpu)
+{
+	return ((u64)VCPU(vcpu, irr[3]));
+}
+
+static inline void vcpu_set_dcr(VCPU *vcpu, u64 val)
+{
+	ia64_set_dcr(val);
+}
+
+static inline void vcpu_set_isr(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, isr) = val;
+}
+
+static inline void vcpu_set_lid(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, lid) = val;
+}
+
+static inline void vcpu_set_ipsr(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, ipsr) = val;
+}
+
+static inline void vcpu_set_iip(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, iip) = val;
+}
+
+static inline void vcpu_set_ifs(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, ifs) = val;
+}
+
+static inline void vcpu_set_iipa(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, iipa) = val;
+}
+
+static inline void vcpu_set_iha(VCPU *vcpu, u64 val)
+{
+	VCPU(vcpu, iha) = val;
+}
+
+
+static inline u64 vcpu_get_rr(VCPU *vcpu, u64 reg)
+{
+	return vcpu->arch.vrr[reg>>61];
+}
+
+/**************************************************************************
+  VCPU debug breakpoint register access routines
+ **************************************************************************/
+
+static inline void vcpu_set_dbr(VCPU *vcpu, u64 reg, u64 val)
+{
+	/* TODO: need to virtualize */
+	__ia64_set_dbr(reg, val);
+}
+
+static inline void vcpu_set_ibr(VCPU *vcpu, u64 reg, u64 val)
+{
+	/* TODO: need to virtualize */
+	ia64_set_ibr(reg, val);
+}
+
+static inline u64 vcpu_get_dbr(VCPU *vcpu, u64 reg)
+{
+	/* TODO: need to virtualize */
+	return ((u64)__ia64_get_dbr(reg));
+}
+
+static inline u64 vcpu_get_ibr(VCPU *vcpu, u64 reg)
+{
+	/* TODO: need to virtualize */
+	return ((u64)ia64_get_ibr(reg));
+}
+
+/**************************************************************************
+  VCPU performance monitor register access routines
+ **************************************************************************/
+static inline void vcpu_set_pmc(VCPU *vcpu, u64 reg, u64 val)
+{
+	/* TODO: need to virtualize */
+	/* NOTE: Writes to unimplemented PMC registers are discarded */
+	ia64_set_pmc(reg, val);
+}
+
+static inline void vcpu_set_pmd(VCPU *vcpu, u64 reg, u64 val)
+{
+	/* TODO: need to virtualize */
+	/* NOTE: Writes to unimplemented PMD registers are discarded */
+	ia64_set_pmd(reg, val);
+}
+
+static inline u64 vcpu_get_pmc(VCPU *vcpu, u64 reg)
+{
+	/* TODO: need to virtualize */
+	/* NOTE: Reads from unimplemented PMC registers return zero */
+	return ((u64)ia64_get_pmc(reg));
+}
+
+static inline u64 vcpu_get_pmd(VCPU *vcpu, u64 reg)
+{
+	/* TODO: need to virtualize */
+	/* NOTE: Reads from unimplemented PMD registers return zero */
+	return ((u64)ia64_get_pmd(reg));
+}
+
+static inline unsigned long vrrtomrr(unsigned long val)
+{
+	ia64_rr rr;
+	rr.val = val;
+	rr.rid = (rr.rid << 4) | 0xe;
+	if (rr.ps > PAGE_SHIFT)
+		rr.ps = PAGE_SHIFT;
+	rr.ve = 1;
+	return rr.val;
+}
+
+
+static inline int highest_bits(int *dat)
+{
+	u32  bits, bitnum;
+	int i;
+
+	/* loop for all 256 bits */
+	for (i = 7; i >= 0 ; i --) {
+		bits = dat[i];
+		if (bits) {
+			bitnum = fls(bits);
+			return i * 32 + bitnum - 1;
+		}
+	}
+	return NULL_VECTOR;
+}
+
+/*
+ * The pending irq is higher than the inservice one.
+ *
+ */
+static inline int is_higher_irq(int pending, int inservice)
+{
+	return ((pending > inservice)
+			|| ((pending != NULL_VECTOR)
+			&& (inservice == NULL_VECTOR)));
+}
+
+static inline int is_higher_class(int pending, int mic)
+{
+	return ((pending >> 4) > mic);
+}
+
+
+/*
+ * Return 0-255 for pending irq.
+ *        NULL_VECTOR: when no pending.
+ */
+static inline int highest_pending_irq(VCPU *vcpu)
+{
+	if (VCPU(vcpu, irr[0]) & (1UL<<NMI_VECTOR))
+		return NMI_VECTOR;
+	if (VCPU(vcpu, irr[0]) & (1UL<<ExtINT_VECTOR))
+		return ExtINT_VECTOR;
+
+	return highest_bits((int *)&VCPU(vcpu, irr[0]));
+}
+
+static inline int highest_inservice_irq(VCPU *vcpu)
+{
+	if (VMX(vcpu, insvc[0]) & (1UL<<NMI_VECTOR))
+		return NMI_VECTOR;
+	if (VMX(vcpu, insvc[0]) & (1UL<<ExtINT_VECTOR))
+		return ExtINT_VECTOR;
+
+	return highest_bits((int *)&(VMX(vcpu, insvc[0])));
+}
+
+extern void vcpu_get_fpreg(VCPU *vcpu, u64 reg, struct ia64_fpreg *val);
+extern void vcpu_set_fpreg(VCPU *vcpu, u64 reg, struct ia64_fpreg *val);
+extern u64 vcpu_get_gr(VCPU *vcpu, u64 reg);
+extern void vcpu_set_gr(VCPU *vcpu, u64 reg, u64 val, int nat);
+extern u64 vcpu_get_psr(VCPU *vcpu);
+extern void vcpu_set_psr(VCPU *vcpu, u64 val);
+extern u64 vcpu_thash(VCPU *vcpu, u64 vadr);
+extern void vcpu_bsw0(VCPU *vcpu);
+extern void thash_vhpt_insert(VCPU *v, u64 pte, u64 itir, u64 va, int type);
+extern thash_data_t *vhpt_lookup(u64 va);
+extern u64 guest_vhpt_lookup(u64 iha, u64 *pte);
+extern void thash_purge_entries(VCPU *v, u64 va, u64 ps);
+extern u64 translate_phy_pte(u64 *pte, u64 itir, u64 va);
+extern int thash_purge_and_insert(VCPU *v, u64 pte,
+					u64 itir, u64 ifa, int type);
+extern void thash_purge_all(VCPU *v);
+extern thash_data_t *vtlb_lookup(VCPU *v, u64 va, int is_data);
+extern int vtr_find_overlap(VCPU *vcpu, u64 va, u64 ps, int is_data);
+
+extern void vcpu_increment_iip(VCPU *v);
+extern void vcpu_decrement_iip(VCPU *vcpu);
+extern void vcpu_pend_interrupt(VCPU *vcpu, u8 vec);
+extern void data_page_not_present(VCPU *vcpu, u64 vadr);
+extern void dnat_page_consumption (VCPU *vcpu, u64 vadr);
+extern void alt_dtlb (VCPU *vcpu, u64 vadr);
+extern void nested_dtlb (VCPU *vcpu);
+extern void dvhpt_fault (VCPU *vcpu, u64 vadr);
+extern int vhpt_enabled(VCPU *vcpu, u64 vadr, vhpt_ref_t ref);
+
+extern void update_vhpi(VCPU *vcpu, int vec);
+extern int irq_masked(VCPU *vcpu, int h_pending, int h_inservice);
+
+extern int fetch_code(VCPU *vcpu, u64 gip, IA64_BUNDLE *pbundle);
+extern void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma);
+extern void vmm_transition(VCPU *vcpu);
+extern void vmm_trampoline(context_t *from, context_t *to);
+extern int vmm_entry(void);
+extern  u64 vcpu_get_itc(VCPU *vcpu);
+
+extern void vmm_reset_entry(void);
+void kvm_init_vtlb(VCPU *v);
+void kvm_init_vhpt(VCPU *v);
+void panic_vm(VCPU *v);
+
+extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2, u64 arg3,
+		u64 arg4, u64 arg5, u64 arg6, u64 arg7);
+#endif
+
+#endif	/* __VCPU_H__ */
diff --git a/arch/ia64/kvm/vti.h b/arch/ia64/kvm/vti.h
new file mode 100644
index 0000000..13a16dc
--- /dev/null
+++ b/arch/ia64/kvm/vti.h
@@ -0,0 +1,293 @@
+/*
+ * vti.h: prototype for generial vt related interface
+ *   	Copyright (c) 2004, Intel Corporation.
+ *
+ *	Xuefei Xu (Anthony Xu) (anthony.xu@intel.com)
+ *	Fred Yang (fred.yang@intel.com)
+ * 	Kun Tian (Kevin Tian) (kevin.tian@intel.com)
+ *
+ *  	Copyright (c) 2007, Intel Corporation.
+ *  	Zhang xiantao <xiantao.zhang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef _KVM_VT_I_H
+#define _KVM_VT_I_H
+
+#ifndef __ASSEMBLY__
+#include <asm/page.h>
+#include <asm/kvm_host.h>
+
+/* define itr.i and itr.d  in ia64_itr function */
+#define	ITR	0x01
+#define	DTR	0x02
+#define	IaDTR	0x03
+
+#define IA64_TR_VMM       6 /*itr6, dtr6 : maps vmm code, vmbuffer*/
+#define IA64_TR_VM_DATA   7 /*dtr7       : maps current vm data*/
+
+#define RR6 (6UL<<61)
+#define RR7 (7UL<<61)
+
+
+/* config_options in pal_vp_init_env */
+#define	VP_INITIALIZE	1UL
+#define	VP_FR_PMC	1UL<<1
+#define	VP_OPCODE	1UL<<8
+#define	VP_CAUSE	1UL<<9
+#define VP_FW_ACC   	1UL<<63
+
+/* init vp env with initializing vm_buffer */
+#define	VP_INIT_ENV_INITALIZE  (VP_INITIALIZE | VP_FR_PMC |\
+	VP_OPCODE | VP_CAUSE | VP_FW_ACC)
+/* init vp env without initializing vm_buffer */
+#define	VP_INIT_ENV  VP_FR_PMC | VP_OPCODE | VP_CAUSE | VP_FW_ACC
+
+#define		PAL_VP_CREATE   265
+/* Stacked Virt. Initializes a new VPD for the operation of
+ * a new virtual processor in the virtual environment.
+ */
+#define		PAL_VP_ENV_INFO 266
+/*Stacked Virt. Returns the parameters needed to enter a virtual environment.*/
+#define		PAL_VP_EXIT_ENV 267
+/*Stacked Virt. Allows a logical processor to exit a virtual environment.*/
+#define		PAL_VP_INIT_ENV 268
+/*Stacked Virt. Allows a logical processor to enter a virtual environment.*/
+#define		PAL_VP_REGISTER 269
+/*Stacked Virt. Register a different host IVT for the virtual processor.*/
+#define		PAL_VP_RESUME   270
+/* Renamed from PAL_VP_RESUME */
+#define		PAL_VP_RESTORE  270
+/*Stacked Virt. Resumes virtual processor operation on the logical processor.*/
+#define		PAL_VP_SUSPEND  271
+/* Renamed from PAL_VP_SUSPEND */
+#define		PAL_VP_SAVE	271
+/* Stacked Virt. Suspends operation for the specified virtual processor on
+ * the logical processor.
+ */
+#define		PAL_VP_TERMINATE 272
+/* Stacked Virt. Terminates operation for the specified virtual processor.*/
+
+union vac {
+	unsigned long value;
+	struct {
+		int a_int:1;
+		int a_from_int_cr:1;
+		int a_to_int_cr:1;
+		int a_from_psr:1;
+		int a_from_cpuid:1;
+		int a_cover:1;
+		int a_bsw:1;
+		long reserved:57;
+	};
+};
+
+typedef union vac vac_t;
+
+union vdc {
+	unsigned long value;
+	struct {
+		int d_vmsw:1;
+		int d_extint:1;
+		int d_ibr_dbr:1;
+		int d_pmc:1;
+		int d_to_pmd:1;
+		int d_itm:1;
+		long reserved:58;
+	};
+};
+typedef union vdc vdc_t;
+
+typedef struct vpd {
+	union vac   vac;
+	union vdc   vdc;
+	unsigned long  virt_env_vaddr;
+	unsigned long  reserved1[29];
+	unsigned long  vhpi;
+	unsigned long  reserved2[95];
+	unsigned long  vgr[16];
+	unsigned long  vbgr[16];
+	unsigned long  vnat;
+	unsigned long  vbnat;
+	unsigned long  vcpuid[5];
+	unsigned long  reserved3[11];
+	unsigned long  vpsr;
+	unsigned long  vpr;
+	unsigned long  reserved4[76];
+	union {
+		unsigned long  vcr[128];
+		struct {
+			unsigned long dcr;
+			unsigned long itm;
+			unsigned long iva;
+			unsigned long rsv1[5];
+			unsigned long pta;
+			unsigned long rsv2[7];
+			unsigned long ipsr;
+			unsigned long isr;
+			unsigned long rsv3;
+			unsigned long iip;
+			unsigned long ifa;
+			unsigned long itir;
+			unsigned long iipa;
+			unsigned long ifs;
+			unsigned long iim;
+			unsigned long iha;
+			unsigned long rsv4[38];
+			unsigned long lid;
+			unsigned long ivr;
+			unsigned long tpr;
+			unsigned long eoi;
+			unsigned long irr[4];
+			unsigned long itv;
+			unsigned long pmv;
+			unsigned long cmcv;
+			unsigned long rsv5[5];
+			unsigned long lrr0;
+			unsigned long lrr1;
+			unsigned long rsv6[46];
+		};
+	};
+	unsigned long  reserved5[128];
+	unsigned long  reserved6[3456];
+	unsigned long  vmm_avail[128];
+	unsigned long  reserved7[4096];
+} vpd_t;
+
+#define PAL_PROC_VM_BIT		(1UL << 40)
+#define PAL_PROC_VMSW_BIT	(1UL << 54)
+
+static inline s64 ia64_pal_vp_env_info(u64 *buffer_size,
+		u64 *vp_env_info)
+{
+	struct ia64_pal_retval iprv;
+	PAL_CALL_STK(iprv, PAL_VP_ENV_INFO, 0, 0, 0);
+	*buffer_size = iprv.v0;
+	*vp_env_info = iprv.v1;
+	return iprv.status;
+}
+
+static inline s64 ia64_pal_vp_exit_env(u64 iva)
+{
+	struct ia64_pal_retval iprv;
+
+	PAL_CALL_STK(iprv, PAL_VP_EXIT_ENV, (u64)iva, 0, 0);
+	return iprv.status;
+}
+
+static inline s64 ia64_pal_vp_init_env (u64 config_options, u64 pbase_addr,
+			u64 vbase_addr, u64 *vsa_base)
+{
+	struct ia64_pal_retval iprv;
+
+	PAL_CALL_STK(iprv, PAL_VP_INIT_ENV, config_options, pbase_addr,
+			vbase_addr);
+	*vsa_base = iprv.v0;
+
+	return iprv.status;
+}
+
+static inline s64 ia64_pal_vp_restore (u64 *vpd, u64 pal_proc_vector)
+{
+	struct ia64_pal_retval iprv;
+
+	PAL_CALL_STK(iprv, PAL_VP_RESTORE, (u64)vpd, pal_proc_vector, 0);
+
+	return iprv.status;
+}
+
+static inline s64 ia64_pal_vp_save (u64 *vpd, u64 pal_proc_vector)
+{
+	struct ia64_pal_retval iprv;
+
+	PAL_CALL_STK(iprv, PAL_VP_SAVE, (u64)vpd, pal_proc_vector, 0);
+
+	return iprv.status;
+}
+
+#endif
+
+/*VPD field offset*/
+#define VPD_VAC_START_OFFSET		0
+#define VPD_VDC_START_OFFSET		8
+#define VPD_VHPI_START_OFFSET		256
+#define VPD_VGR_START_OFFSET		1024
+#define VPD_VBGR_START_OFFSET		1152
+#define VPD_VNAT_START_OFFSET		1280
+#define VPD_VBNAT_START_OFFSET		1288
+#define VPD_VCPUID_START_OFFSET		1296
+#define VPD_VPSR_START_OFFSET		1424
+#define VPD_VPR_START_OFFSET		1432
+#define VPD_VRSE_CFLE_START_OFFSET	1440
+#define VPD_VCR_START_OFFSET		2048
+#define VPD_VTPR_START_OFFSET		2576
+#define VPD_VRR_START_OFFSET		3072
+#define VPD_VMM_VAIL_START_OFFSET	31744
+
+/*Virtualization faults*/
+
+#define EVENT_MOV_TO_AR			 1
+#define EVENT_MOV_TO_AR_IMM		 2
+#define EVENT_MOV_FROM_AR		 3
+#define EVENT_MOV_TO_CR			 4
+#define EVENT_MOV_FROM_CR		 5
+#define EVENT_MOV_TO_PSR		 6
+#define EVENT_MOV_FROM_PSR		 7
+#define EVENT_ITC_D			 8
+#define EVENT_ITC_I			 9
+#define EVENT_MOV_TO_RR			 10
+#define EVENT_MOV_TO_DBR		 11
+#define EVENT_MOV_TO_IBR		 12
+#define EVENT_MOV_TO_PKR		 13
+#define EVENT_MOV_TO_PMC		 14
+#define EVENT_MOV_TO_PMD		 15
+#define EVENT_ITR_D			 16
+#define EVENT_ITR_I			 17
+#define EVENT_MOV_FROM_RR		 18
+#define EVENT_MOV_FROM_DBR		 19
+#define EVENT_MOV_FROM_IBR		 20
+#define EVENT_MOV_FROM_PKR		 21
+#define EVENT_MOV_FROM_PMC		 22
+#define EVENT_MOV_FROM_CPUID		 23
+#define EVENT_SSM			 24
+#define EVENT_RSM			 25
+#define EVENT_PTC_L			 26
+#define EVENT_PTC_G			 27
+#define EVENT_PTC_GA			 28
+#define EVENT_PTR_D			 29
+#define EVENT_PTR_I			 30
+#define EVENT_THASH			 31
+#define EVENT_TTAG			 32
+#define EVENT_TPA			 33
+#define EVENT_TAK			 34
+#define EVENT_PTC_E			 35
+#define EVENT_COVER			 36
+#define EVENT_RFI			 37
+#define EVENT_BSW_0			 38
+#define EVENT_BSW_1			 39
+#define EVENT_VMSW			 40
+
+/**PAL virtual services offsets */
+#define PAL_VPS_RESUME_NORMAL           0x0000
+#define PAL_VPS_RESUME_HANDLER          0x0400
+#define PAL_VPS_SYNC_READ               0x0800
+#define PAL_VPS_SYNC_WRITE              0x0c00
+#define PAL_VPS_SET_PENDING_INTERRUPT   0x1000
+#define PAL_VPS_THASH                   0x1400
+#define PAL_VPS_TTAG                    0x1800
+#define PAL_VPS_RESTORE                 0x1c00
+#define PAL_VPS_SAVE                    0x2000
+
+#endif/* _VT_I_H*/
+/* -*-  Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
-- 
1.5.2


[-- Attachment #7: Type: text/plain, Size: 308 bytes --]

-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services
for just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

[-- Attachment #8: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [kvm-devel] [1-5/17] Patch 1-10 of kvm/ia64 V2
       [not found] ` <42DFA526FC41B1429CE7279EF83C6BDCB139D3-wq7ZOvIWXbMAbVU2wMM1CrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2007-12-21  7:07     ` Akio Takebe
  2007-12-21  7:44     ` Akio Takebe
  1 sibling, 0 replies; 9+ messages in thread
From: Akio Takebe @ 2007-12-21  7:07 UTC (permalink / raw)
  To: Zhang, Xiantao, kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: Luck, Tony, linux-ia64-u79uwXL29TY76Z2rM5mHXA, Avi Kivity

Hi, Xiantao

I got reading kvm-ia64 started. :)
Which member is p2m table?

> [2/17] Add kvm-ia64.c to support kvm module on Itanium processors.
Some trivial comments.

+int kvm_arch_init(void *opaque)
+{
+	int r;
+	struct kvm_vmm_info *vmm_info = (struct kvm_vmm_info *)opaque;
+
+	if (kvm_vmm_info) {
+		printk(KERN_ERR "kvm: already loaded the other module!\n");
+		r = -EEXIST;
+		goto out;
+	}
+
+	r =  -ENOMEM;
extra white space.

+	kvm_vmm_info = kzalloc(sizeof(struct kvm_vmm_info), GFP_KERNEL);
+	if (!kvm_vmm_info)
+		goto out;
+
Can we get the message of shortage of memory by qemu?

+	if (!vti_cpu_has_kvm_support()) {
+		printk(KERN_ERR "kvm: no hardware support\n");
+		r = -EOPNOTSUPP;
+		goto out_free0;
+	}
+
We had better check vti support at the first.

+	kvm_hack_insert_tr();
+
+	if (kvm_alloc_vmm_area())
+		goto out_free0;
+
r = kvm_alloc_vmm_area() is better.

+	r = kvm_relocate_vmm(vmm_info, vmm_info->module);
+	if (r)
+		goto out_free1;
+
+	return 0;
+
+out_free1:
+	kvm_free_vmm_area();
+out_free0:
+	kfree(kvm_vmm_info);
+out:
+	return r;
+}
+
+void kvm_arch_exit(void)
+{
+	kvm_free_vmm_area();
+	kfree(kvm_vmm_info);
+	kvm_vmm_info = 0;
+}
kvm_vmm_info = (void *)0?

Best Regards,

Akio Takebe


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [1-5/17] Patch 1-10 of kvm/ia64 V2
@ 2007-12-21  7:07     ` Akio Takebe
  0 siblings, 0 replies; 9+ messages in thread
From: Akio Takebe @ 2007-12-21  7:07 UTC (permalink / raw)
  To: Zhang, Xiantao, kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: Luck, Tony, linux-ia64-u79uwXL29TY76Z2rM5mHXA, Avi Kivity

Hi, Xiantao

I got reading kvm-ia64 started. :)
Which member is p2m table?

> [2/17] Add kvm-ia64.c to support kvm module on Itanium processors.
Some trivial comments.

+int kvm_arch_init(void *opaque)
+{
+	int r;
+	struct kvm_vmm_info *vmm_info = (struct kvm_vmm_info *)opaque;
+
+	if (kvm_vmm_info) {
+		printk(KERN_ERR "kvm: already loaded the other module!\n");
+		r = -EEXIST;
+		goto out;
+	}
+
+	r =  -ENOMEM;
extra white space.

+	kvm_vmm_info = kzalloc(sizeof(struct kvm_vmm_info), GFP_KERNEL);
+	if (!kvm_vmm_info)
+		goto out;
+
Can we get the message of shortage of memory by qemu?

+	if (!vti_cpu_has_kvm_support()) {
+		printk(KERN_ERR "kvm: no hardware support\n");
+		r = -EOPNOTSUPP;
+		goto out_free0;
+	}
+
We had better check vti support at the first.

+	kvm_hack_insert_tr();
+
+	if (kvm_alloc_vmm_area())
+		goto out_free0;
+
r = kvm_alloc_vmm_area() is better.

+	r = kvm_relocate_vmm(vmm_info, vmm_info->module);
+	if (r)
+		goto out_free1;
+
+	return 0;
+
+out_free1:
+	kvm_free_vmm_area();
+out_free0:
+	kfree(kvm_vmm_info);
+out:
+	return r;
+}
+
+void kvm_arch_exit(void)
+{
+	kvm_free_vmm_area();
+	kfree(kvm_vmm_info);
+	kvm_vmm_info = 0;
+}
kvm_vmm_info = (void *)0?

Best Regards,

Akio Takebe


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [kvm-devel] [1-5/17] Patch 1-10 of kvm/ia64 V2
       [not found] ` <42DFA526FC41B1429CE7279EF83C6BDCB139D3-wq7ZOvIWXbMAbVU2wMM1CrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2007-12-21  7:44     ` Akio Takebe
  2007-12-21  7:44     ` Akio Takebe
  1 sibling, 0 replies; 9+ messages in thread
From: Akio Takebe @ 2007-12-21  7:44 UTC (permalink / raw)
  To: Zhang, Xiantao, kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: Luck, Tony, linux-ia64-u79uwXL29TY76Z2rM5mHXA, Avi Kivity

Hi, Xiantao

>> [3/17] Add firmware virtualization support.

+void kvm_sal_emul(struct kvm_vcpu *vcpu)
+{
+
+	struct sal_ret_values result;
+	u64 index, in1, in2, in3, in4, in5, in6, in7;
+
+	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
+			&in3, &in4, &in5, &in6, &in7);
+	if (index) {
+		result = sal_emulator(index, in1, in2, in3,
+						in4, in5, in6, in7);
+		set_sal_result(vcpu, result);
+	} else
+		printk(KERN_WARNING"kvm:Unsupported sal call called,"
+					" index:%d!\n", index);
+}
The printk always show index:0.
And set_sal_result() doesn't work at the time of index=0.
So I think the following code is better.

+void kvm_sal_emul(struct kvm_vcpu *vcpu)
+{
+
+	struct sal_ret_values result;
+	u64 index, in1, in2, in3, in4, in5, in6, in7;
+
+	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
+			&in3, &in4, &in5, &in6, &in7);
+	result = sal_emulator(index, in1, in2, in3,
+					in4, in5, in6, in7);
+	set_sal_result(vcpu, result);
+}

Best Regards,

Akio Takebe


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [1-5/17] Patch 1-10 of kvm/ia64 V2
@ 2007-12-21  7:44     ` Akio Takebe
  0 siblings, 0 replies; 9+ messages in thread
From: Akio Takebe @ 2007-12-21  7:44 UTC (permalink / raw)
  To: Zhang, Xiantao, kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: Luck, Tony, linux-ia64-u79uwXL29TY76Z2rM5mHXA, Avi Kivity

Hi, Xiantao

>> [3/17] Add firmware virtualization support.

+void kvm_sal_emul(struct kvm_vcpu *vcpu)
+{
+
+	struct sal_ret_values result;
+	u64 index, in1, in2, in3, in4, in5, in6, in7;
+
+	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
+			&in3, &in4, &in5, &in6, &in7);
+	if (index) {
+		result = sal_emulator(index, in1, in2, in3,
+						in4, in5, in6, in7);
+		set_sal_result(vcpu, result);
+	} else
+		printk(KERN_WARNING"kvm:Unsupported sal call called,"
+					" index:%d!\n", index);
+}
The printk always show index:0.
And set_sal_result() doesn't work at the time of index=0.
So I think the following code is better.

+void kvm_sal_emul(struct kvm_vcpu *vcpu)
+{
+
+	struct sal_ret_values result;
+	u64 index, in1, in2, in3, in4, in5, in6, in7;
+
+	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
+			&in3, &in4, &in5, &in6, &in7);
+	result = sal_emulator(index, in1, in2, in3,
+					in4, in5, in6, in7);
+	set_sal_result(vcpu, result);
+}

Best Regards,

Akio Takebe


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [kvm-devel] [1-5/17] Patch 1-10 of kvm/ia64 V2
  2007-12-21  7:07     ` Akio Takebe
@ 2007-12-21  7:44       ` Zhang, Xiantao
  -1 siblings, 0 replies; 9+ messages in thread
From: Zhang, Xiantao @ 2007-12-21  7:44 UTC (permalink / raw)
  To: Akio Takebe, kvm-devel; +Cc: Luck, Tony, linux-ia64, Avi Kivity

Hi Akio,
	Thank you for your comments.
Xiantao
Akio Takebe wrote:
> Hi, Xiantao
m: already loaded the other module!\n");
> +		r = -EEXIST;
> +		goto out;
> +	}
> +
> +	r =  -ENOMEM;
> extra white space.

Yes.  One more white space here.

> +	kvm_vmm_info = kzalloc(sizeof(struct kvm_vmm_info), GFP_KERNEL);
> +	if (!kvm_vmm_info)
> +		goto out;
> +
> Can we get the message of shortage of memory by qemu?

The memory allocation here is just for vmm module initialization, and no
qemu/vm created so far. 
Memory shortage here, will leads to module insert fail, and this is our
expectable result.  

> +	if (!vti_cpu_has_kvm_support()) {
> +		printk(KERN_ERR "kvm: no hardware support\n");
> +		r = -EOPNOTSUPP;
> +		goto out_free0;
> +	}
> +
> We had better check vti support at the first.

OK,  I will move it to first in arch_init. :)

> +}
> kvm_vmm_info = (void *)0?

Maybe NULL is better :)

> 
>
------------------------------------------------------------------------
-
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2005.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> kvm-devel mailing list
> kvm-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/kvm-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [kvm-devel] [1-5/17] Patch 1-10 of kvm/ia64 V2
@ 2007-12-21  7:44       ` Zhang, Xiantao
  0 siblings, 0 replies; 9+ messages in thread
From: Zhang, Xiantao @ 2007-12-21  7:44 UTC (permalink / raw)
  To: Akio Takebe, kvm-devel; +Cc: Luck, Tony, linux-ia64, Avi Kivity

Hi Akio,
	Thank you for your comments.
Xiantao
Akio Takebe wrote:
> Hi, Xiantao
m: already loaded the other module!\n");
> +		r = -EEXIST;
> +		goto out;
> +	}
> +
> +	r =  -ENOMEM;
> extra white space.

Yes.  One more white space here.

> +	kvm_vmm_info = kzalloc(sizeof(struct kvm_vmm_info), GFP_KERNEL);
> +	if (!kvm_vmm_info)
> +		goto out;
> +
> Can we get the message of shortage of memory by qemu?

The memory allocation here is just for vmm module initialization, and no
qemu/vm created so far. 
Memory shortage here, will leads to module insert fail, and this is our
expectable result.  

> +	if (!vti_cpu_has_kvm_support()) {
> +		printk(KERN_ERR "kvm: no hardware support\n");
> +		r = -EOPNOTSUPP;
> +		goto out_free0;
> +	}
> +
> We had better check vti support at the first.

OK,  I will move it to first in arch_init. :)

> +}
> kvm_vmm_info = (void *)0?

Maybe NULL is better :)

> 
>
------------------------------------------------------------------------
-
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2005.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> kvm-devel mailing list
> kvm-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/kvm-devel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [kvm-devel] [1-5/17] Patch 1-10 of kvm/ia64 V2
  2007-12-21  7:44     ` Akio Takebe
@ 2007-12-21  8:14       ` Zhang, Xiantao
  -1 siblings, 0 replies; 9+ messages in thread
From: Zhang, Xiantao @ 2007-12-21  8:14 UTC (permalink / raw)
  To: Akio Takebe, kvm-devel; +Cc: Luck, Tony, linux-ia64, Avi Kivity

Akio Takebe wrote:
> Hi, Xiantao
> 
>>> [3/17] Add firmware virtualization support.
> 
> +void kvm_sal_emul(struct kvm_vcpu *vcpu)
> +{
> +
> +	struct sal_ret_values result;
> +	u64 index, in1, in2, in3, in4, in5, in6, in7;
> +
> +	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
> +			&in3, &in4, &in5, &in6, &in7);
> +	if (index) {
> +		result = sal_emulator(index, in1, in2, in3,
> +						in4, in5, in6, in7);
> +		set_sal_result(vcpu, result);
> +	} else
> +		printk(KERN_WARNING"kvm:Unsupported sal call called,"
> +					" index:%d!\n", index);
> +}
> The printk always show index:0.
> And set_sal_result() doesn't work at the time of index=0.
> So I think the following code is better.

Good catch! Originally, I want to use it for kvm_get_sal_call debug, but
forget to remove it. 
Thank you! :)

> +void kvm_sal_emul(struct kvm_vcpu *vcpu)
> +{
> +
> +	struct sal_ret_values result;
> +	u64 index, in1, in2, in3, in4, in5, in6, in7;
> +
> +	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
> +			&in3, &in4, &in5, &in6, &in7);
> +	result = sal_emulator(index, in1, in2, in3,
> +					in4, in5, in6, in7);
> +	set_sal_result(vcpu, result);
> +}
> 
> Best Regards,
> 
> Akio Takebe


^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [kvm-devel] [1-5/17] Patch 1-10 of kvm/ia64 V2
@ 2007-12-21  8:14       ` Zhang, Xiantao
  0 siblings, 0 replies; 9+ messages in thread
From: Zhang, Xiantao @ 2007-12-21  8:14 UTC (permalink / raw)
  To: Akio Takebe, kvm-devel; +Cc: Luck, Tony, linux-ia64, Avi Kivity

Akio Takebe wrote:
> Hi, Xiantao
> 
>>> [3/17] Add firmware virtualization support.
> 
> +void kvm_sal_emul(struct kvm_vcpu *vcpu)
> +{
> +
> +	struct sal_ret_values result;
> +	u64 index, in1, in2, in3, in4, in5, in6, in7;
> +
> +	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
> +			&in3, &in4, &in5, &in6, &in7);
> +	if (index) {
> +		result = sal_emulator(index, in1, in2, in3,
> +						in4, in5, in6, in7);
> +		set_sal_result(vcpu, result);
> +	} else
> +		printk(KERN_WARNING"kvm:Unsupported sal call called,"
> +					" index:%d!\n", index);
> +}
> The printk always show index:0.
> And set_sal_result() doesn't work at the time of index=0.
> So I think the following code is better.

Good catch! Originally, I want to use it for kvm_get_sal_call debug, but
forget to remove it. 
Thank you! :)

> +void kvm_sal_emul(struct kvm_vcpu *vcpu)
> +{
> +
> +	struct sal_ret_values result;
> +	u64 index, in1, in2, in3, in4, in5, in6, in7;
> +
> +	kvm_get_sal_call_data(vcpu, &index, &in1, &in2,
> +			&in3, &in4, &in5, &in6, &in7);
> +	result = sal_emulator(index, in1, in2, in3,
> +					in4, in5, in6, in7);
> +	set_sal_result(vcpu, result);
> +}
> 
> Best Regards,
> 
> Akio Takebe


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2007-12-21  8:14 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-20  5:46 [1-5/17] Patch 1-10 of kvm/ia64 V2 Zhang, Xiantao
     [not found] ` <42DFA526FC41B1429CE7279EF83C6BDCB139D3-wq7ZOvIWXbMAbVU2wMM1CrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2007-12-21  7:07   ` [kvm-devel] " Akio Takebe
2007-12-21  7:07     ` Akio Takebe
2007-12-21  7:44     ` [kvm-devel] " Zhang, Xiantao
2007-12-21  7:44       ` Zhang, Xiantao
2007-12-21  7:44   ` Akio Takebe
2007-12-21  7:44     ` Akio Takebe
2007-12-21  8:14     ` [kvm-devel] " Zhang, Xiantao
2007-12-21  8:14       ` Zhang, Xiantao

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.