* [PATCH 01/28] ia64/xen: introduce ia64_set_rr0_to_rr4() to make kernel paravirtualization friendly.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 02/28] ia64/xen: introduce ia64_get_psr_i() " yamahata
` (31 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0001-ia64-xen-introduce-ia64_set_rr0_to_rr4-to-make-ke.patch --]
[-- Type: text/plain, Size: 1734 bytes --]
ia64/Xen will replace setting rr[0-4] with single hypercall later.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
include/asm-ia64/intrinsics.h | 10 ++++++++++
include/asm-ia64/mmu_context.h | 6 +-----
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h
index f1135b5..c206755 100644
--- a/include/asm-ia64/intrinsics.h
+++ b/include/asm-ia64/intrinsics.h
@@ -18,6 +18,15 @@
# include <asm/gcc_intrin.h>
#endif
+#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \
+do { \
+ ia64_set_rr(0x0000000000000000UL, (val0)); \
+ ia64_set_rr(0x2000000000000000UL, (val1)); \
+ ia64_set_rr(0x4000000000000000UL, (val2)); \
+ ia64_set_rr(0x6000000000000000UL, (val3)); \
+ ia64_set_rr(0x8000000000000000UL, (val4)); \
+} while (0)
+
/*
* Force an unresolved reference if someone tries to use
* ia64_fetch_and_add() with a bad value.
@@ -183,4 +192,5 @@ extern long ia64_cmpxchg_called_with_bad_pointer (void);
#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
#endif
+#include <asm/privop.h>
#endif /* _ASM_IA64_INTRINSICS_H */
diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
index cef2400..040bc87 100644
--- a/include/asm-ia64/mmu_context.h
+++ b/include/asm-ia64/mmu_context.h
@@ -152,11 +152,7 @@ reload_context (nv_mm_context_t context)
# endif
#endif
- ia64_set_rr(0x0000000000000000UL, rr0);
- ia64_set_rr(0x2000000000000000UL, rr1);
- ia64_set_rr(0x4000000000000000UL, rr2);
- ia64_set_rr(0x6000000000000000UL, rr3);
- ia64_set_rr(0x8000000000000000UL, rr4);
+ ia64_set_rr0_to_rr4(rr0, rr1, rr2, rr3, rr4);
ia64_srlz_i(); /* srlz.i implies srlz.d */
}
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 02/28] ia64/xen: introduce ia64_get_psr_i() to make kernel paravirtualization friendly.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
2008-02-21 9:17 ` [PATCH 01/28] ia64/xen: introduce ia64_set_rr0_to_rr4() to make kernel paravirtualization friendly yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 03/28] ia64/xen: increase IA64_MAX_RSVD_REGIONS yamahata
` (30 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0002-ia64-xen-introduce-ia64_get_psr_i-to-make-kernel.patch --]
[-- Type: text/plain, Size: 1640 bytes --]
__local_irq_save() and local_save_flags() are used to mask interruptions.
They read all psr bits that requres whole bit emulation.
On the other hand, reading only psr.i, the single bit, can be virtualized
cheaply.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
include/asm-ia64/intrinsics.h | 2 ++
include/asm-ia64/system.h | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h
index c206755..5800ad0 100644
--- a/include/asm-ia64/intrinsics.h
+++ b/include/asm-ia64/intrinsics.h
@@ -18,6 +18,8 @@
# include <asm/gcc_intrin.h>
#endif
+#define ia64_get_psr_i() (ia64_getreg(_IA64_REG_PSR) & IA64_PSR_I)
+
#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \
do { \
ia64_set_rr(0x0000000000000000UL, (val0)); \
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 595112b..2bca73e 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -125,7 +125,7 @@ extern struct ia64_boot_param {
#define __local_irq_save(x) \
do { \
ia64_stop(); \
- (x) = ia64_getreg(_IA64_REG_PSR); \
+ (x) = ia64_get_psr_i(); \
ia64_stop(); \
ia64_rsm(IA64_PSR_I); \
} while (0)
@@ -173,7 +173,7 @@ do { \
#endif /* !CONFIG_IA64_DEBUG_IRQ */
#define local_irq_enable() ({ ia64_stop(); ia64_ssm(IA64_PSR_I); ia64_srlz_d(); })
-#define local_save_flags(flags) ({ ia64_stop(); (flags) = ia64_getreg(_IA64_REG_PSR); })
+#define local_save_flags(flags) ({ ia64_stop(); (flags) = ia64_get_psr_i(); })
#define irqs_disabled() \
({ \
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 03/28] ia64/xen: increase IA64_MAX_RSVD_REGIONS.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
2008-02-21 9:17 ` [PATCH 01/28] ia64/xen: introduce ia64_set_rr0_to_rr4() to make kernel paravirtualization friendly yamahata
2008-02-21 9:17 ` [PATCH 02/28] ia64/xen: introduce ia64_get_psr_i() " yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 04/28] ia64/xen: introduce synch bitops which is necessary for ia64/xen support yamahata
` (29 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0003-ia64-xen-increase-IA64_MAX_RSVD_REGIONS.patch --]
[-- Type: text/plain, Size: 859 bytes --]
Xenlinux/ia64 needs to reserve one more region passed from xen hypervisor
as start info.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
include/asm-ia64/meminit.h | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
index f93308f..7c12c08 100644
--- a/include/asm-ia64/meminit.h
+++ b/include/asm-ia64/meminit.h
@@ -18,10 +18,17 @@
* - crash dumping code reserved region
* - Kernel memory map built from EFI memory map
* - ELF core header
+ * ifdef CONFIG_XEN
+ * - xen start info
+ * endif
*
* More could be added if necessary
*/
+#ifdef CONFIG_XEN
#define IA64_MAX_RSVD_REGIONS 8
+#else
+#define IA64_MAX_RSVD_REGIONS 9
+#endif
struct rsvd_region {
unsigned long start; /* virtual address of beginning of element */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 04/28] ia64/xen: introduce synch bitops which is necessary for ia64/xen support.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (2 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 03/28] ia64/xen: increase IA64_MAX_RSVD_REGIONS yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 05/28] ia64/xen: import xen hypercall header file yamahata
` (28 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0004-ia64-xen-introduce-synch-bitops-which-is-necessary.patch --]
[-- Type: text/plain, Size: 1873 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
include/asm-ia64/sync_bitops.h | 61 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 61 insertions(+), 0 deletions(-)
create mode 100644 include/asm-ia64/sync_bitops.h
diff --git a/include/asm-ia64/sync_bitops.h b/include/asm-ia64/sync_bitops.h
new file mode 100644
index 0000000..dc402be
--- /dev/null
+++ b/include/asm-ia64/sync_bitops.h
@@ -0,0 +1,61 @@
+#ifndef __XEN_SYNC_BITOPS_H__
+#define __XEN_SYNC_BITOPS_H__
+
+/*
+ * Copyright 1992, Linus Torvalds.
+ * Heavily modified to provide guaranteed strong synchronisation
+ * when communicating with Xen or other guest OSes running on other CPUs.
+ */
+
+#define ADDR (*(volatile long *) addr)
+
+static inline void sync_set_bit(int nr, volatile void *addr)
+{
+ set_bit(nr, addr);
+}
+
+static inline void sync_clear_bit(int nr, volatile void *addr)
+{
+ clear_bit(nr, addr);
+}
+
+static inline void sync_change_bit(int nr, volatile void *addr)
+{
+ change_bit(nr, addr);
+}
+
+static inline int sync_test_and_set_bit(int nr, volatile void *addr)
+{
+ return test_and_set_bit(nr, addr);
+}
+
+static inline int sync_test_and_clear_bit(int nr, volatile void *addr)
+{
+ return test_and_clear_bit(nr, addr);
+}
+
+static inline int sync_test_and_change_bit(int nr, volatile void *addr)
+{
+ return test_and_change_bit(nr, addr);
+}
+
+static inline int sync_const_test_bit(int nr, const volatile void *addr)
+{
+ return test_bit(nr, addr);
+}
+
+static inline int sync_var_test_bit(int nr, volatile void *addr)
+{
+ return test_bit(nr, addr);
+}
+
+#define sync_cmpxchg ia64_cmpxchg4_acq
+
+#define sync_test_bit(nr,addr) \
+ (__builtin_constant_p(nr) ? \
+ sync_const_test_bit((nr), (addr)) : \
+ sync_var_test_bit((nr), (addr)))
+
+#define sync_cmpxchg_subword sync_cmpxchg
+
+#endif /* __XEN_SYNC_BITOPS_H__ */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 05/28] ia64/xen: import xen hypercall header file.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (3 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 04/28] ia64/xen: introduce synch bitops which is necessary for ia64/xen support yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 06/28] ia64/xen: define xen assembler constants which will be used later yamahata
` (27 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0005-ia64-xen-import-xen-hypercall-header-file.patch --]
[-- Type: text/plain, Size: 24133 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
include/asm-ia64/xen/interface.h | 686 ++++++++++++++++++++++++++++++++++++++
1 files changed, 686 insertions(+), 0 deletions(-)
create mode 100644 include/asm-ia64/xen/interface.h
diff --git a/include/asm-ia64/xen/interface.h b/include/asm-ia64/xen/interface.h
new file mode 100644
index 0000000..69418f6
--- /dev/null
+++ b/include/asm-ia64/xen/interface.h
@@ -0,0 +1,686 @@
+/******************************************************************************
+ * arch-ia64/hypervisor-if.h
+ *
+ * Guest OS interface to IA64 Xen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __HYPERVISOR_IF_IA64_H__
+#define __HYPERVISOR_IF_IA64_H__
+
+/*
+ * TODO:
+ * linux's interface header removed XEN prefix
+ * Now just work around
+ */
+#define DEFINE_GUEST_HANDLE_STRUCT(name) \
+ __DEFINE_XEN_GUEST_HANDLE(name, struct name)
+#define DEFINE_GUEST_HANDLE(name) DEFINE_XEN_GUEST_HANDLE(name)
+#define GUEST_HANDLE(name) XEN_GUEST_HANDLE(name)
+
+/* Structural guest handles introduced in 0x00030201. */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030201
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef struct { type *p; } __guest_handle_ ## name
+#else
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+ typedef type * __guest_handle_ ## name
+#endif
+
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+ ___DEFINE_XEN_GUEST_HANDLE(name, type)
+#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define XEN_GUEST_HANDLE(name) __guest_handle_ ## name
+#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
+#define uint64_aligned_t uint64_t
+#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)
+#ifdef __XEN_TOOLS__
+#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
+#endif
+
+#ifndef __ASSEMBLY__
+/* Guest handles for primitive C types. */
+__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
+__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int);
+__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
+__DEFINE_XEN_GUEST_HANDLE(u64, unsigned long);
+DEFINE_XEN_GUEST_HANDLE(char);
+DEFINE_XEN_GUEST_HANDLE(int);
+DEFINE_XEN_GUEST_HANDLE(long);
+DEFINE_XEN_GUEST_HANDLE(void);
+
+typedef unsigned long xen_pfn_t;
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
+#define PRI_xen_pfn "lx"
+#endif
+
+/* Arch specific VIRQs definition */
+#define VIRQ_ITC VIRQ_ARCH_0 /* V. Virtual itc timer */
+#define VIRQ_MCA_CMC VIRQ_ARCH_1 /* MCA cmc interrupt */
+#define VIRQ_MCA_CPE VIRQ_ARCH_2 /* MCA cpe interrupt */
+
+/* Maximum number of virtual CPUs in multi-processor guests. */
+/* WARNING: before changing this, check that shared_info fits on a page */
+#define MAX_VIRT_CPUS 64
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long xen_ulong_t;
+
+#ifdef __XEN_TOOLS__
+#define XEN_PAGE_SIZE XC_PAGE_SIZE
+#else
+#define XEN_PAGE_SIZE PAGE_SIZE
+#endif
+
+#define INVALID_MFN (~0UL)
+
+#define MEM_G (1UL << 30)
+#define MEM_M (1UL << 20)
+#define MEM_K (1UL << 10)
+
+/* Guest physical address of IO ports space. */
+#define IO_PORTS_PADDR 0x00000ffffc000000UL
+#define IO_PORTS_SIZE 0x0000000004000000UL
+
+#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_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE)
+#define IO_PAGE_SIZE XEN_PAGE_SIZE
+
+#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE)
+#define STORE_PAGE_SIZE XEN_PAGE_SIZE
+
+#define BUFFER_IO_PAGE_START (STORE_PAGE_START + STORE_PAGE_SIZE)
+#define BUFFER_IO_PAGE_SIZE XEN_PAGE_SIZE
+
+#define BUFFER_PIO_PAGE_START (BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE)
+#define BUFFER_PIO_PAGE_SIZE XEN_PAGE_SIZE
+
+#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)
+
+/* Nvram belongs to GFW memory space */
+#define NVRAM_SIZE (MEM_K * 64)
+#define NVRAM_START (GFW_START + 10 * MEM_M)
+
+#define NVRAM_VALID_SIG 0x4650494e45584948 /* "HIXENIPF" */
+struct nvram_save_addr {
+ unsigned long addr;
+ unsigned long signature;
+};
+
+struct pt_fpreg {
+ union {
+ unsigned long bits[2];
+ long double __dummy; /* force 16-byte alignment */
+ } u;
+};
+
+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;
+
+struct mapped_regs {
+ union vac vac;
+ union vdc vdc;
+ unsigned long virt_env_vaddr;
+ unsigned long reserved1[29];
+ unsigned long vhpi;
+ unsigned long reserved2[95];
+ union {
+ unsigned long vgr[16];
+ unsigned long bank1_regs[16]; /* bank1 regs (r16-r31) when bank0 active */
+ };
+ union {
+ unsigned long vbgr[16];
+ unsigned long bank0_regs[16]; /* bank0 regs (r16-r31) when bank1 active */
+ };
+ 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; /* CR0 */
+ unsigned long itm;
+ unsigned long iva;
+ unsigned long rsv1[5];
+ unsigned long pta; /* CR8 */
+ unsigned long rsv2[7];
+ unsigned long ipsr; /* CR16 */
+ unsigned long isr;
+ unsigned long rsv3;
+ unsigned long iip;
+ unsigned long ifa;
+ unsigned long itir;
+ unsigned long iipa;
+ unsigned long ifs;
+ unsigned long iim; /* CR24 */
+ unsigned long iha;
+ unsigned long rsv4[38];
+ unsigned long lid; /* CR64 */
+ unsigned long ivr;
+ unsigned long tpr;
+ unsigned long eoi;
+ unsigned long irr[4];
+ unsigned long itv; /* CR72 */
+ unsigned long pmv;
+ unsigned long cmcv;
+ unsigned long rsv5[5];
+ unsigned long lrr0; /* CR80 */
+ unsigned long lrr1;
+ unsigned long rsv6[46];
+ };
+ };
+ union {
+ unsigned long reserved5[128];
+ struct {
+ unsigned long precover_ifs;
+ unsigned long unat; /* not sure if this is needed until
+ NaT arch is done */
+ int interrupt_collection_enabled; /* virtual psr.ic */
+ /* virtual interrupt deliverable flag is evtchn_upcall_mask in
+ * shared info area now. interrupt_mask_addr is the address
+ * of evtchn_upcall_mask for current vcpu
+ */
+ unsigned char *interrupt_mask_addr;
+ int pending_interruption;
+ unsigned char vpsr_pp;
+ unsigned char vpsr_dfh;
+ unsigned char hpsr_dfh;
+ unsigned char hpsr_mfh;
+ unsigned long reserved5_1[4];
+ int metaphysical_mode; /* 1 = use metaphys mapping
+ 0 = use virtual */
+ int banknum; /* 0 or 1, which virtual register
+ bank is active */
+ unsigned long rrs[8]; /* region registers */
+ unsigned long krs[8]; /* kernel registers */
+ unsigned long tmp[16]; /* temp registers
+ (e.g. for hyperprivops) */
+ };
+ };
+};
+typedef struct mapped_regs mapped_regs_t;
+
+struct vpd {
+ struct mapped_regs vpd_low;
+ unsigned long reserved6[3456];
+ unsigned long vmm_avail[128];
+ unsigned long reserved7[4096];
+};
+typedef struct vpd vpd_t;
+
+struct arch_vcpu_info {
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+/*
+ * This structure is used for magic page in domain pseudo physical address
+ * space and the result of XENMEM_machine_memory_map.
+ * As the XENMEM_machine_memory_map result,
+ * xen_memory_map::nr_entries indicates the size in bytes
+ * including struct xen_ia64_memmap_info. Not the number of entries.
+ */
+struct xen_ia64_memmap_info {
+ uint64_t efi_memmap_size; /* size of EFI memory map */
+ uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */
+ uint32_t efi_memdesc_version; /* memory descriptor version */
+ void *memdesc[0]; /* array of efi_memory_desc_t */
+};
+typedef struct xen_ia64_memmap_info xen_ia64_memmap_info_t;
+
+struct arch_shared_info {
+ /* PFN of the start_info page. */
+ unsigned long start_info_pfn;
+
+ /* Interrupt vector for event channel. */
+ int evtchn_vector;
+
+ /* PFN of memmap_info page */
+ unsigned int memmap_info_num_pages; /* currently only = 1 case is
+ supported. */
+ unsigned long memmap_info_pfn;
+
+ uint64_t pad[31];
+};
+typedef struct arch_shared_info arch_shared_info_t;
+
+typedef unsigned long xen_callback_t;
+
+struct ia64_tr_entry {
+ unsigned long pte;
+ unsigned long itir;
+ unsigned long vadr;
+ unsigned long rid;
+};
+typedef struct ia64_tr_entry ia64_tr_entry_t;
+DEFINE_XEN_GUEST_HANDLE(ia64_tr_entry_t);
+
+struct vcpu_tr_regs {
+ struct ia64_tr_entry itrs[12];
+ struct ia64_tr_entry dtrs[12];
+};
+
+union vcpu_ar_regs {
+ unsigned long ar[128];
+ struct {
+ unsigned long kr[8];
+ unsigned long rsv1[8];
+ unsigned long rsc;
+ unsigned long bsp;
+ unsigned long bspstore;
+ unsigned long rnat;
+ unsigned long rsv2;
+ unsigned long fcr;
+ unsigned long rsv3[2];
+ unsigned long eflag;
+ unsigned long csd;
+ unsigned long ssd;
+ unsigned long cflg;
+ unsigned long fsr;
+ unsigned long fir;
+ unsigned long fdr;
+ unsigned long rsv4;
+ unsigned long ccv; /* 32 */
+ unsigned long rsv5[3];
+ unsigned long unat;
+ unsigned long rsv6[3];
+ unsigned long fpsr;
+ unsigned long rsv7[3];
+ unsigned long itc;
+ unsigned long rsv8[3];
+ unsigned long ign1[16];
+ unsigned long pfs; /* 64 */
+ unsigned long lc;
+ unsigned long ec;
+ unsigned long rsv9[45];
+ unsigned long ign2[16];
+ };
+};
+
+union vcpu_cr_regs {
+ unsigned long cr[128];
+ struct {
+ unsigned long dcr; /* CR0 */
+ unsigned long itm;
+ unsigned long iva;
+ unsigned long rsv1[5];
+ unsigned long pta; /* CR8 */
+ unsigned long rsv2[7];
+ unsigned long ipsr; /* CR16 */
+ unsigned long isr;
+ unsigned long rsv3;
+ unsigned long iip;
+ unsigned long ifa;
+ unsigned long itir;
+ unsigned long iipa;
+ unsigned long ifs;
+ unsigned long iim; /* CR24 */
+ unsigned long iha;
+ unsigned long rsv4[38];
+ unsigned long lid; /* CR64 */
+ unsigned long ivr;
+ unsigned long tpr;
+ unsigned long eoi;
+ unsigned long irr[4];
+ unsigned long itv; /* CR72 */
+ unsigned long pmv;
+ unsigned long cmcv;
+ unsigned long rsv5[5];
+ unsigned long lrr0; /* CR80 */
+ unsigned long lrr1;
+ unsigned long rsv6[46];
+ };
+};
+
+struct vcpu_guest_context_regs {
+ unsigned long r[32];
+ unsigned long b[8];
+ unsigned long bank[16];
+ unsigned long ip;
+ unsigned long psr;
+ unsigned long cfm;
+ unsigned long pr;
+ unsigned int nats; /* NaT bits for r1-r31. */
+ unsigned int bnats; /* Nat bits for banked registers. */
+ union vcpu_ar_regs ar;
+ union vcpu_cr_regs cr;
+ struct pt_fpreg f[128];
+ unsigned long dbr[8];
+ unsigned long ibr[8];
+ unsigned long rr[8];
+ unsigned long pkr[16];
+
+ /* FIXME: cpuid,pmd,pmc */
+
+ unsigned long xip;
+ unsigned long xpsr;
+ unsigned long xfs;
+ unsigned long xr[4];
+
+ struct vcpu_tr_regs tr;
+
+ /* Physical registers in case of debug event. */
+ unsigned long excp_iipa;
+ unsigned long excp_ifa;
+ unsigned long excp_isr;
+ unsigned int excp_vector;
+
+ /*
+ * The rbs is intended to be the image of the stacked registers still
+ * in the cpu (not yet stored in memory). It is laid out as if it
+ * were written in memory at a 512 (64*8) aligned address + offset.
+ * rbs_voff is (offset / 8). rbs_nat contains NaT bits for the
+ * remaining rbs registers. rbs_rnat contains NaT bits for in memory
+ * rbs registers.
+ * Note: loadrs is 2**14 bytes == 2**11 slots.
+ */
+ unsigned int rbs_voff;
+ unsigned long rbs[2048];
+ unsigned long rbs_rnat;
+
+ /*
+ * RSE.N_STACKED_PHYS via PAL_RSE_INFO
+ * Strictly this isn't cpu context, but this value is necessary
+ * for domain save/restore. So is here.
+ */
+ unsigned long num_phys_stacked;
+};
+
+struct vcpu_guest_context {
+#define VGCF_EXTRA_REGS (1UL << 1) /* Set extra regs. */
+#define VGCF_SET_CR_IRR (1UL << 2) /* Set cr_irr[0:3]. */
+ unsigned long flags; /* VGCF_* flags */
+
+ struct vcpu_guest_context_regs regs;
+
+ unsigned long event_callback_ip;
+
+ /* xen doesn't share privregs pages with hvm domain so that this member
+ * doesn't make sense for hvm domain.
+ * ~0UL is already used for INVALID_P2M_ENTRY. */
+#define VGC_PRIVREGS_HVM (~(-2UL))
+ unsigned long privregs_pfn;
+};
+typedef struct vcpu_guest_context vcpu_guest_context_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
+
+/* dom0 vp op */
+#define __HYPERVISOR_ia64_dom0vp_op __HYPERVISOR_arch_0
+/* Map io space in machine address to dom0 physical address space.
+ Currently physical assigned address equals to machine address. */
+#define IA64_DOM0VP_ioremap 0
+
+/* Convert a pseudo physical page frame number to the corresponding
+ machine page frame number. If no page is assigned, INVALID_MFN or
+ GPFN_INV_MASK is returned depending on domain's non-vti/vti mode. */
+#define IA64_DOM0VP_phystomach 1
+
+/* Convert a machine page frame number to the corresponding pseudo physical
+ page frame number of the caller domain. */
+#define IA64_DOM0VP_machtophys 3
+
+/* Reserved for future use. */
+#define IA64_DOM0VP_iounmap 4
+
+/* Unmap and free pages contained in the specified pseudo physical region. */
+#define IA64_DOM0VP_zap_physmap 5
+
+/* Assign machine page frame to dom0's pseudo physical address space. */
+#define IA64_DOM0VP_add_physmap 6
+
+/* expose the p2m table into domain */
+#define IA64_DOM0VP_expose_p2m 7
+
+/* xen perfmon */
+#define IA64_DOM0VP_perfmon 8
+
+/* gmfn version of IA64_DOM0VP_add_physmap */
+#define IA64_DOM0VP_add_physmap_with_gmfn 9
+
+/* get fpswa revision */
+#define IA64_DOM0VP_fpswa_revision 10
+
+/* Add an I/O port space range */
+#define IA64_DOM0VP_add_io_space 11
+
+/* expose the foreign domain's p2m table into privileged domain */
+#define IA64_DOM0VP_expose_foreign_p2m 12
+#define IA64_DOM0VP_EFP_ALLOC_PTE 0x1 /* allocate p2m table */
+
+/* unexpose the foreign domain's p2m table into privileged domain */
+#define IA64_DOM0VP_unexpose_foreign_p2m 13
+
+/* replace this page with newly allocated one and track tlb insert on it. */
+#define IA64_DOM0VP_tlb_track_page 32
+
+/* assign a page with newly allocated one and track tlb insert on it.
+ if page is already assigned to pseudo physical address it results
+ in error. */
+#define IA64_DOM0VP_tlb_add_track_page 33
+
+/* disable tlb traking of this page */
+#define IA64_DOM0VP_tlb_untrack_page 34
+
+
+/* flags for page assignement to pseudo physical address space */
+#define _ASSIGN_readonly 0
+#define ASSIGN_readonly (1UL << _ASSIGN_readonly)
+#define ASSIGN_writable (0UL << _ASSIGN_readonly) /* dummy flag */
+/* Internal only: memory attribute must be WC/UC/UCE. */
+#define _ASSIGN_nocache 1
+#define ASSIGN_nocache (1UL << _ASSIGN_nocache)
+/* tlb tracking */
+#define _ASSIGN_tlb_track 2
+#define ASSIGN_tlb_track (1UL << _ASSIGN_tlb_track)
+/* Internal only: associated with PGC_allocated bit */
+#define _ASSIGN_pgc_allocated 3
+#define ASSIGN_pgc_allocated (1UL << _ASSIGN_pgc_allocated)
+
+/* This structure has the same layout of struct ia64_boot_param, defined in
+ <asm/system.h>. It is redefined here to ease use. */
+struct xen_ia64_boot_param {
+ unsigned long command_line; /* physical address of cmd line args */
+ unsigned long efi_systab; /* physical address of EFI system table */
+ unsigned long efi_memmap; /* physical address of EFI memory map */
+ unsigned long efi_memmap_size; /* size of EFI memory map */
+ unsigned long efi_memdesc_size; /* size of an EFI memory map descriptor */
+ unsigned int efi_memdesc_version; /* memory descriptor version */
+ struct {
+ unsigned short num_cols; /* number of columns on console. */
+ unsigned short num_rows; /* number of rows on console. */
+ unsigned short orig_x; /* cursor's x position */
+ unsigned short orig_y; /* cursor's y position */
+ } console_info;
+ unsigned long fpswa; /* physical address of the fpswa interface */
+ unsigned long initrd_start;
+ unsigned long initrd_size;
+ unsigned long domain_start; /* va where the boot time domain begins */
+ unsigned long domain_size; /* how big is the boot domain */
+};
+
+#endif /* !__ASSEMBLY__ */
+
+/* Size of the shared_info area (this is not related to page size). */
+#define XSI_SHIFT 14
+#define XSI_SIZE (1 << XSI_SHIFT)
+/* Log size of mapped_regs area (64 KB - only 4KB is used). */
+#define XMAPPEDREGS_SHIFT 12
+#define XMAPPEDREGS_SIZE (1 << XMAPPEDREGS_SHIFT)
+/* Offset of XASI (Xen arch shared info) wrt XSI_BASE. */
+#define XMAPPEDREGS_OFS XSI_SIZE
+
+/* Hyperprivops. */
+#define HYPERPRIVOP_START 0x1
+#define HYPERPRIVOP_RFI (HYPERPRIVOP_START + 0x0)
+#define HYPERPRIVOP_RSM_DT (HYPERPRIVOP_START + 0x1)
+#define HYPERPRIVOP_SSM_DT (HYPERPRIVOP_START + 0x2)
+#define HYPERPRIVOP_COVER (HYPERPRIVOP_START + 0x3)
+#define HYPERPRIVOP_ITC_D (HYPERPRIVOP_START + 0x4)
+#define HYPERPRIVOP_ITC_I (HYPERPRIVOP_START + 0x5)
+#define HYPERPRIVOP_SSM_I (HYPERPRIVOP_START + 0x6)
+#define HYPERPRIVOP_GET_IVR (HYPERPRIVOP_START + 0x7)
+#define HYPERPRIVOP_GET_TPR (HYPERPRIVOP_START + 0x8)
+#define HYPERPRIVOP_SET_TPR (HYPERPRIVOP_START + 0x9)
+#define HYPERPRIVOP_EOI (HYPERPRIVOP_START + 0xa)
+#define HYPERPRIVOP_SET_ITM (HYPERPRIVOP_START + 0xb)
+#define HYPERPRIVOP_THASH (HYPERPRIVOP_START + 0xc)
+#define HYPERPRIVOP_PTC_GA (HYPERPRIVOP_START + 0xd)
+#define HYPERPRIVOP_ITR_D (HYPERPRIVOP_START + 0xe)
+#define HYPERPRIVOP_GET_RR (HYPERPRIVOP_START + 0xf)
+#define HYPERPRIVOP_SET_RR (HYPERPRIVOP_START + 0x10)
+#define HYPERPRIVOP_SET_KR (HYPERPRIVOP_START + 0x11)
+#define HYPERPRIVOP_FC (HYPERPRIVOP_START + 0x12)
+#define HYPERPRIVOP_GET_CPUID (HYPERPRIVOP_START + 0x13)
+#define HYPERPRIVOP_GET_PMD (HYPERPRIVOP_START + 0x14)
+#define HYPERPRIVOP_GET_EFLAG (HYPERPRIVOP_START + 0x15)
+#define HYPERPRIVOP_SET_EFLAG (HYPERPRIVOP_START + 0x16)
+#define HYPERPRIVOP_RSM_BE (HYPERPRIVOP_START + 0x17)
+#define HYPERPRIVOP_GET_PSR (HYPERPRIVOP_START + 0x18)
+#define HYPERPRIVOP_SET_RR0_TO_RR4 (HYPERPRIVOP_START + 0x19)
+#define HYPERPRIVOP_MAX (0x1a)
+
+/* Fast and light hypercalls. */
+#define __HYPERVISOR_ia64_fast_eoi __HYPERVISOR_arch_1
+
+/* Extra debug features. */
+#define __HYPERVISOR_ia64_debug_op __HYPERVISOR_arch_2
+
+/* Xencomm macros. */
+#define XENCOMM_INLINE_MASK 0xf800000000000000UL
+#define XENCOMM_INLINE_FLAG 0x8000000000000000UL
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Optimization features.
+ * The hypervisor may do some special optimizations for guests. This hypercall
+ * can be used to switch on/of these special optimizations.
+ */
+#define __HYPERVISOR_opt_feature 0x700UL
+
+#define XEN_IA64_OPTF_OFF 0x0
+#define XEN_IA64_OPTF_ON 0x1
+
+/*
+ * If this feature is switched on, the hypervisor inserts the
+ * tlb entries without calling the guests traphandler.
+ * This is useful in guests using region 7 for identity mapping
+ * like the linux kernel does.
+ */
+#define XEN_IA64_OPTF_IDENT_MAP_REG7 1
+
+/* Identity mapping of region 4 addresses in HVM. */
+#define XEN_IA64_OPTF_IDENT_MAP_REG4 2
+
+/* Identity mapping of region 5 addresses in HVM. */
+#define XEN_IA64_OPTF_IDENT_MAP_REG5 3
+
+#define XEN_IA64_OPTF_IDENT_MAP_NOT_SET (0)
+
+struct xen_ia64_opt_feature {
+ unsigned long cmd; /* Which feature */
+ unsigned char on; /* Switch feature on/off */
+ union {
+ struct {
+ /* The page protection bit mask of the pte.
+ * This will be or'ed with the pte. */
+ unsigned long pgprot;
+ unsigned long key; /* A protection key for itir. */
+ };
+ };
+};
+
+#endif /* __ASSEMBLY__ */
+
+/* xen perfmon */
+#ifdef XEN
+#ifndef __ASSEMBLY__
+#ifndef _ASM_IA64_PERFMON_H
+
+#include <xen/list.h> /* asm/perfmon.h requires struct list_head */
+#include <asm/perfmon.h>
+/* for PFM_xxx and pfarg_features_t, pfarg_context_t, pfarg_reg_t, pfarg_load_t */
+
+#endif /* _ASM_IA64_PERFMON_H */
+
+DEFINE_XEN_GUEST_HANDLE(pfarg_features_t);
+DEFINE_XEN_GUEST_HANDLE(pfarg_context_t);
+DEFINE_XEN_GUEST_HANDLE(pfarg_reg_t);
+DEFINE_XEN_GUEST_HANDLE(pfarg_load_t);
+#endif /* __ASSEMBLY__ */
+#endif /* XEN */
+
+#endif /* __HYPERVISOR_IF_IA64_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 06/28] ia64/xen: define xen assembler constants which will be used later.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (4 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 05/28] ia64/xen: import xen hypercall header file yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 07/28] ia64/xen: detect xen environment at early boot time and do minimal initialization yamahata
` (26 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0006-ia64-xen-define-xen-assembler-constants-which-will.patch --]
[-- Type: text/plain, Size: 4760 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/asm-offsets.c | 25 ++++++++++++++
include/asm-ia64/xen/privop.h | 73 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 0 deletions(-)
create mode 100644 include/asm-ia64/xen/privop.h
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index 0aebc6f..b432638 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -278,4 +278,29 @@ void foo(void)
offsetof (struct itc_jitter_data_t, itc_jitter));
DEFINE(IA64_ITC_LASTCYCLE_OFFSET,
offsetof (struct itc_jitter_data_t, itc_lastcycle));
+
+#ifdef CONFIG_XEN
+ BLANK();
+
+#define DEFINE_MAPPED_REG_OFS(sym, field) \
+ DEFINE(sym, (XMAPPEDREGS_OFS + offsetof(mapped_regs_t, field)))
+
+ DEFINE_MAPPED_REG_OFS(XSI_PSR_I_ADDR_OFS, interrupt_mask_addr);
+ DEFINE_MAPPED_REG_OFS(XSI_IPSR_OFS, ipsr);
+ DEFINE_MAPPED_REG_OFS(XSI_IIP_OFS, iip);
+ DEFINE_MAPPED_REG_OFS(XSI_IFS_OFS, ifs);
+ DEFINE_MAPPED_REG_OFS(XSI_PRECOVER_IFS_OFS, precover_ifs);
+ DEFINE_MAPPED_REG_OFS(XSI_ISR_OFS, isr);
+ DEFINE_MAPPED_REG_OFS(XSI_IFA_OFS, ifa);
+ DEFINE_MAPPED_REG_OFS(XSI_IIPA_OFS, iipa);
+ DEFINE_MAPPED_REG_OFS(XSI_IIM_OFS, iim);
+ DEFINE_MAPPED_REG_OFS(XSI_IHA_OFS, iha);
+ DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir);
+ DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled);
+ DEFINE_MAPPED_REG_OFS(XSI_BANKNUM_OFS, banknum);
+ DEFINE_MAPPED_REG_OFS(XSI_BANK0_R16_OFS, bank0_regs[0]);
+ DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]);
+ DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat);
+ DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat);
+#endif /* CONFIG_XEN */
}
diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h
new file mode 100644
index 0000000..dd3e5ec
--- /dev/null
+++ b/include/asm-ia64/xen/privop.h
@@ -0,0 +1,73 @@
+#ifndef _ASM_IA64_XEN_PRIVOP_H
+#define _ASM_IA64_XEN_PRIVOP_H
+
+/*
+ * Copyright (C) 2005 Hewlett-Packard Co
+ * Dan Magenheimer <dan.magenheimer@hp.com>
+ *
+ * Paravirtualizations of privileged operations for Xen/ia64
+ *
+ *
+ * inline privop and paravirt_alt support
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ */
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h> /* arch-ia64.h requires uint64_t */
+#include <linux/stringify.h>
+#endif
+#include <asm/xen/interface.h>
+
+/* At 1 MB, before per-cpu space but still addressable using addl instead
+ of movl. */
+#define XSI_BASE 0xfffffffffff00000
+
+/* Address of mapped regs. */
+#define XMAPPEDREGS_BASE (XSI_BASE + XSI_SIZE)
+
+#ifdef __ASSEMBLY__
+#define XEN_HYPER_RFI break HYPERPRIVOP_RFI
+#define XEN_HYPER_RSM_PSR_DT break HYPERPRIVOP_RSM_DT
+#define XEN_HYPER_SSM_PSR_DT break HYPERPRIVOP_SSM_DT
+#define XEN_HYPER_COVER break HYPERPRIVOP_COVER
+#define XEN_HYPER_ITC_D break HYPERPRIVOP_ITC_D
+#define XEN_HYPER_ITC_I break HYPERPRIVOP_ITC_I
+#define XEN_HYPER_SSM_I break HYPERPRIVOP_SSM_I
+#define XEN_HYPER_GET_IVR break HYPERPRIVOP_GET_IVR
+#define XEN_HYPER_GET_TPR break HYPERPRIVOP_GET_TPR
+#define XEN_HYPER_SET_TPR break HYPERPRIVOP_SET_TPR
+#define XEN_HYPER_EOI break HYPERPRIVOP_EOI
+#define XEN_HYPER_SET_ITM break HYPERPRIVOP_SET_ITM
+#define XEN_HYPER_THASH break HYPERPRIVOP_THASH
+#define XEN_HYPER_PTC_GA break HYPERPRIVOP_PTC_GA
+#define XEN_HYPER_ITR_D break HYPERPRIVOP_ITR_D
+#define XEN_HYPER_GET_RR break HYPERPRIVOP_GET_RR
+#define XEN_HYPER_SET_RR break HYPERPRIVOP_SET_RR
+#define XEN_HYPER_SET_KR break HYPERPRIVOP_SET_KR
+#define XEN_HYPER_FC break HYPERPRIVOP_FC
+#define XEN_HYPER_GET_CPUID break HYPERPRIVOP_GET_CPUID
+#define XEN_HYPER_GET_PMD break HYPERPRIVOP_GET_PMD
+#define XEN_HYPER_GET_EFLAG break HYPERPRIVOP_GET_EFLAG
+#define XEN_HYPER_SET_EFLAG break HYPERPRIVOP_SET_EFLAG
+#define XEN_HYPER_GET_PSR break HYPERPRIVOP_GET_PSR
+#define XEN_HYPER_SET_RR0_TO_RR4 break HYPERPRIVOP_SET_RR0_TO_RR4
+
+#define XSI_IFS (XSI_BASE + XSI_IFS_OFS)
+#define XSI_PRECOVER_IFS (XSI_BASE + XSI_PRECOVER_IFS_OFS)
+#define XSI_IFA (XSI_BASE + XSI_IFA_OFS)
+#define XSI_ISR (XSI_BASE + XSI_ISR_OFS)
+#define XSI_IIM (XSI_BASE + XSI_IIM_OFS)
+#define XSI_ITIR (XSI_BASE + XSI_ITIR_OFS)
+#define XSI_PSR_I_ADDR (XSI_BASE + XSI_PSR_I_ADDR_OFS)
+#define XSI_PSR_IC (XSI_BASE + XSI_PSR_IC_OFS)
+#define XSI_IPSR (XSI_BASE + XSI_IPSR_OFS)
+#define XSI_IIP (XSI_BASE + XSI_IIP_OFS)
+#define XSI_B1NAT (XSI_BASE + XSI_B1NATS_OFS)
+#define XSI_BANK1_R16 (XSI_BASE + XSI_BANK1_R16_OFS)
+#define XSI_BANKNUM (XSI_BASE + XSI_BANKNUM_OFS)
+#define XSI_IHA (XSI_BASE + XSI_IHA_OFS)
+#endif
+
+#endif /* _ASM_IA64_XEN_PRIVOP_H */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 07/28] ia64/xen: detect xen environment at early boot time and do minimal initialization.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (5 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 06/28] ia64/xen: define xen assembler constants which will be used later yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 08/28] RFC: ia64/xen: xen hand written assembly code paravirtualization yamahata
` (25 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0007-ia64-xen-detect-xen-environment-at-early-boot-time.patch --]
[-- Type: text/plain, Size: 4657 bytes --]
Currently it detects by checking psr.cpl != 0.
It's ok for now, but more abstraction would be needed later like x86.
Presumably extending booting protocol (i.e. extending struct ia64_boot_param)
or multi entry points depending on hypervisor would be necessary.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/head.S | 6 ++++
arch/ia64/xen/xensetup.S | 40 +++++++++++++++++++++++++++
include/asm-ia64/xen/hypervisor.h | 55 +++++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+), 0 deletions(-)
create mode 100644 arch/ia64/xen/xensetup.S
create mode 100644 include/asm-ia64/xen/hypervisor.h
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index d3a41d5..2f8d770 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -367,6 +367,12 @@ start_ap:
;;
(isBP) st8 [r2]=r28 // save the address of the boot param area passed by the bootloader
+#ifdef CONFIG_XEN
+ // Note: isBP is used by the subprogram.
+ br.call.sptk.many rp=early_xen_setup
+ ;;
+#endif
+
#ifdef CONFIG_SMP
(isAP) br.call.sptk.many rp=start_secondary
.ret0:
diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S
new file mode 100644
index 0000000..17ad297
--- /dev/null
+++ b/arch/ia64/xen/xensetup.S
@@ -0,0 +1,40 @@
+/*
+ * Support routines for Xen
+ *
+ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
+ */
+
+#include <asm/processor.h>
+#include <asm/asmmacro.h>
+
+ .section .data.read_mostly
+ .align 8
+ .global running_on_xen
+running_on_xen:
+ data4 0
+ .previous
+
+#define isBP p3 // are we the Bootstrap Processor?
+
+ .text
+GLOBAL_ENTRY(early_xen_setup)
+ mov r8=ar.rsc // Initialized in head.S
+(isBP) movl r9=running_on_xen;;
+ extr.u r8=r8,2,2;; // Extract pl fields
+ cmp.eq p7,p0=r8,r0 // p7: !running on xen
+ mov r8=1 // booleanize.
+(p7) br.ret.sptk.many rp;;
+(isBP) st4 [r9]=r8
+ movl r10=xen_ivt;;
+
+ mov cr.iva=r10
+
+ /* Set xsi base. */
+#define FW_HYPERCALL_SET_SHARED_INFO_VA 0x600
+(isBP) mov r2=FW_HYPERCALL_SET_SHARED_INFO_VA
+(isBP) movl r28=XSI_BASE;;
+(isBP) break 0x1000;;
+
+ br.ret.sptk.many rp
+ ;;
+END(early_xen_setup)
diff --git a/include/asm-ia64/xen/hypervisor.h b/include/asm-ia64/xen/hypervisor.h
new file mode 100644
index 0000000..4ee50c9
--- /dev/null
+++ b/include/asm-ia64/xen/hypervisor.h
@@ -0,0 +1,55 @@
+/******************************************************************************
+ * hypervisor.h
+ *
+ * Linux-specific hypervisor handling.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERVISOR_H__
+#define __HYPERVISOR_H__
+
+#ifdef CONFIG_XEN
+/* running_on_xen is set before executing any C code by early_xen_setup */
+extern const int running_on_xen;
+#define is_running_on_xen() (running_on_xen)
+#else /* CONFIG_XEN */
+# ifdef CONFIG_VMX_GUEST
+# define is_running_on_xen() (1)
+# else /* CONFIG_VMX_GUEST */
+# define is_running_on_xen() (0)
+# endif /* CONFIG_VMX_GUEST */
+#endif /* CONFIG_XEN */
+
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+#define is_initial_xendomain() \
+ (is_running_on_xen() ? xen_start_info->flags & SIF_INITDOMAIN : 0)
+#else
+#define is_initial_xendomain() 0
+#endif
+
+#endif /* __HYPERVISOR_H__ */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 08/28] RFC: ia64/xen: xen hand written assembly code paravirtualization.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (6 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 07/28] ia64/xen: detect xen environment at early boot time and do minimal initialization yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 09/28] ia64/xen: paravirtualize pal_call_static() yamahata
` (24 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0008-ia64-xen-xen-hand-written-assembly-code-paravirtual.patch --]
[-- Type: text/plain, Size: 102489 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/entry.S | 41 +-
arch/ia64/xen/xenentry.S | 798 +++++++++++++++
arch/ia64/xen/xenivt.S | 2204 +++++++++++++++++++++++++++++++++++++++++
arch/ia64/xen/xenminstate.h | 320 ++++++
include/asm-ia64/privop.h | 26 +
include/asm-ia64/xen/privop.h | 22 +
6 files changed, 3399 insertions(+), 12 deletions(-)
create mode 100644 arch/ia64/xen/xenentry.S
create mode 100644 arch/ia64/xen/xenivt.S
create mode 100644 arch/ia64/xen/xenminstate.h
create mode 100644 include/asm-ia64/privop.h
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 3c331c4..39bb7d5 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -180,7 +180,7 @@ END(sys_clone)
* called. The code starting at .map relies on this. The rest of the code
* doesn't care about the interrupt masking status.
*/
-GLOBAL_ENTRY(ia64_switch_to)
+GLOBAL_ENTRY(__ia64_switch_to)
.prologue
alloc r16=ar.pfs,1,0,0,0
DO_SAVE_SWITCH_STACK
@@ -234,7 +234,7 @@ GLOBAL_ENTRY(ia64_switch_to)
;;
srlz.d
br.cond.sptk .done
-END(ia64_switch_to)
+END(__ia64_switch_to)
/*
* Note that interrupts are enabled during save_switch_stack and load_switch_stack. This
@@ -375,7 +375,7 @@ END(save_switch_stack)
* - b7 holds address to return to
* - must not touch r8-r11
*/
-ENTRY(load_switch_stack)
+GLOBAL_ENTRY(load_switch_stack)
.prologue
.altrp b7
@@ -635,8 +635,16 @@ GLOBAL_ENTRY(ia64_ret_from_syscall)
adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
mov r10=r0 // clear error indication in r10
(p7) br.cond.spnt handle_syscall_error // handle potential syscall failure
+#ifdef CONFIG_PARAVIRT_GUEST
+ ;;
+ // don't fall through, ia64_leave_syscall may be #define'd
+ br.cond.sptk.few ia64_leave_syscall
+ ;;
+#endif
END(ia64_ret_from_syscall)
+#ifndef CONFIG_PARAVIRT_GUEST
// fall through
+#endif
/*
* ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
* need to switch to bank 0 and doesn't restore the scratch registers.
@@ -681,7 +689,7 @@ END(ia64_ret_from_syscall)
* ar.csd: cleared
* ar.ssd: cleared
*/
-ENTRY(ia64_leave_syscall)
+GLOBAL_ENTRY(__ia64_leave_syscall)
PT_REGS_UNWIND_INFO(0)
/*
* work.need_resched etc. mustn't get changed by this CPU before it returns to
@@ -691,7 +699,7 @@ ENTRY(ia64_leave_syscall)
* extra work. We always check for extra work when returning to user-level.
* With CONFIG_PREEMPT, we also check for extra work when the preempt_count
* is 0. After extra work processing has been completed, execution
- * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
+ * resumes at ia64_work_processed_syscall with p6 set to 1 if the extra-work-check
* needs to be redone.
*/
#ifdef CONFIG_PREEMPT
@@ -709,7 +717,8 @@ ENTRY(ia64_leave_syscall)
cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
#endif
-.work_processed_syscall:
+.global __ia64_work_processed_syscall;
+__ia64_work_processed_syscall:
adds r2=PT(LOADRS)+16,r12
adds r3=PT(AR_BSPSTORE)+16,r12
adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
@@ -788,7 +797,7 @@ ENTRY(ia64_leave_syscall)
mov.m ar.ssd=r0 // M2 clear ar.ssd
mov f11=f0 // F clear f11
br.cond.sptk.many rbs_switch // B
-END(ia64_leave_syscall)
+END(__ia64_leave_syscall)
#ifdef CONFIG_IA32_SUPPORT
GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
@@ -800,10 +809,18 @@ GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit
.mem.offset 8,0
st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit
+#ifdef CONFIG_PARAVIRT_GUEST
+ ;;
+ // don't fall through, ia64_leave_kernel may be #define'd
+ br.cond.sptk.few ia64_leave_kernel
+ ;;
+#endif
END(ia64_ret_from_ia32_execve)
+#ifndef CONFIG_PARAVIRT_GUEST
// fall through
+#endif
#endif /* CONFIG_IA32_SUPPORT */
-GLOBAL_ENTRY(ia64_leave_kernel)
+GLOBAL_ENTRY(__ia64_leave_kernel)
PT_REGS_UNWIND_INFO(0)
/*
* work.need_resched etc. mustn't get changed by this CPU before it returns to
@@ -1130,9 +1147,9 @@ skip_rbs_switch:
;;
ld8 r8=[r2]
ld8 r10=[r3]
- br.cond.sptk.many .work_processed_syscall // re-check
+ br.cond.sptk.many ia64_work_processed_syscall // re-check
-END(ia64_leave_kernel)
+END(__ia64_leave_kernel)
ENTRY(handle_syscall_error)
/*
@@ -1172,7 +1189,7 @@ END(ia64_invoke_schedule_tail)
* be set up by the caller. We declare 8 input registers so the system call
* args get preserved, in case we need to restart a system call.
*/
-ENTRY(notify_resume_user)
+GLOBAL_ENTRY(notify_resume_user)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
mov r9=ar.unat
@@ -1234,7 +1251,7 @@ ENTRY(sys_rt_sigreturn)
adds sp=16,sp
;;
ld8 r9=[sp] // load new ar.unat
- mov.sptk b7=r8,ia64_leave_kernel
+ mov.sptk b7=r8,__ia64_leave_kernel
;;
mov ar.unat=r9
br.many b7
diff --git a/arch/ia64/xen/xenentry.S b/arch/ia64/xen/xenentry.S
new file mode 100644
index 0000000..38a509d
--- /dev/null
+++ b/arch/ia64/xen/xenentry.S
@@ -0,0 +1,798 @@
+/*
+ * ia64/xen/entry.S
+ *
+ * Alternate kernel routines for Xen. Heavily leveraged from
+ * ia64/kernel/entry.S
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ * Dan Magenheimer <dan.magenheimer@.hp.com>
+ */
+
+#include <asm/asmmacro.h>
+#include <asm/cache.h>
+#include <asm/errno.h>
+#include <asm/kregs.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable.h>
+#include <asm/percpu.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+
+#ifdef CONFIG_XEN
+#include "xenminstate.h"
+#include <asm/paravirt_nop.h>
+#else
+#include "minstate.h"
+#endif
+
+/*
+ * prev_task <- ia64_switch_to(struct task_struct *next)
+ * With Ingo's new scheduler, interrupts are disabled when this routine gets
+ * called. The code starting at .map relies on this. The rest of the code
+ * doesn't care about the interrupt masking status.
+ */
+#ifdef CONFIG_XEN
+GLOBAL_ENTRY(xen_switch_to)
+ BR_IF_NATIVE(__ia64_switch_to, r22, p7)
+#else
+GLOBAL_ENTRY(ia64_switch_to)
+#endif
+ .prologue
+ alloc r16=ar.pfs,1,0,0,0
+ DO_SAVE_SWITCH_STACK
+ .body
+
+ adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
+ movl r25=init_task
+ mov r27=IA64_KR(CURRENT_STACK)
+ adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
+ dep r20=0,in0,61,3 // physical address of "next"
+ ;;
+ st8 [r22]=sp // save kernel stack pointer of old task
+ shr.u r26=r20,IA64_GRANULE_SHIFT
+ cmp.eq p7,p6=r25,in0
+ ;;
+ /*
+ * If we've already mapped this task's page, we can skip doing it again.
+ */
+(p6) cmp.eq p7,p6=r26,r27
+(p6) br.cond.dpnt .map
+ ;;
+.done:
+ ld8 sp=[r21] // load kernel stack pointer of new task
+#ifdef CONFIG_XEN
+ // update "current" application register
+ mov r8=IA64_KR_CURRENT
+ mov r9=in0;;
+ XEN_HYPER_SET_KR
+#else
+ mov IA64_KR(CURRENT)=in0 // update "current" application register
+#endif
+ mov r8=r13 // return pointer to previously running task
+ mov r13=in0 // set "current" pointer
+ ;;
+ DO_LOAD_SWITCH_STACK
+
+#ifdef CONFIG_SMP
+ sync.i // ensure "fc"s done by this CPU are visible on other CPUs
+#endif
+ br.ret.sptk.many rp // boogie on out in new context
+
+.map:
+#ifdef CONFIG_XEN
+ movl r25=XSI_PSR_IC // clear psr.ic
+ ;;
+ st4 [r25]=r0
+ ;;
+#else
+ rsm psr.ic // interrupts (psr.i) are already disabled here
+#endif
+ movl r25=PAGE_KERNEL
+ ;;
+ srlz.d
+ or r23=r25,r20 // construct PA | page properties
+ mov r25=IA64_GRANULE_SHIFT<<2
+ ;;
+#ifdef CONFIG_XEN
+ movl r8=XSI_ITIR
+ ;;
+ st8 [r8]=r25
+ ;;
+ movl r8=XSI_IFA
+ ;;
+ st8 [r8]=in0 // VA of next task...
+ ;;
+ mov r25=IA64_TR_CURRENT_STACK
+ // remember last page we mapped...
+ mov r8=IA64_KR_CURRENT_STACK
+ mov r9=r26;;
+ XEN_HYPER_SET_KR;;
+#else
+ mov cr.itir=r25
+ mov cr.ifa=in0 // VA of next task...
+ ;;
+ mov r25=IA64_TR_CURRENT_STACK
+ mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped...
+#endif
+ ;;
+ itr.d dtr[r25]=r23 // wire in new mapping...
+#ifdef CONFIG_XEN
+ ;;
+ srlz.d
+ mov r9=1
+ movl r8=XSI_PSR_IC
+ ;;
+ st4 [r8]=r9
+ ;;
+#else
+ ssm psr.ic // reenable the psr.ic bit
+ ;;
+ srlz.d
+#endif
+ br.cond.sptk .done
+#ifdef CONFIG_XEN
+END(xen_switch_to)
+#else
+END(ia64_switch_to)
+#endif
+
+#ifdef CONFIG_XEN
+GLOBAL_ENTRY(xen_work_processed_syscall_with_check)
+ BR_IF_NATIVE(__ia64_work_processed_syscall, r2, p7)
+ br.cond.sptk xen_work_processed_syscall
+END(xen_work_processed_syscall_with_check)
+#endif
+
+/*
+ * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
+ * need to switch to bank 0 and doesn't restore the scratch registers.
+ * To avoid leaking kernel bits, the scratch registers are set to
+ * the following known-to-be-safe values:
+ *
+ * r1: restored (global pointer)
+ * r2: cleared
+ * r3: 1 (when returning to user-level)
+ * r8-r11: restored (syscall return value(s))
+ * r12: restored (user-level stack pointer)
+ * r13: restored (user-level thread pointer)
+ * r14: set to __kernel_syscall_via_epc
+ * r15: restored (syscall #)
+ * r16-r17: cleared
+ * r18: user-level b6
+ * r19: cleared
+ * r20: user-level ar.fpsr
+ * r21: user-level b0
+ * r22: cleared
+ * r23: user-level ar.bspstore
+ * r24: user-level ar.rnat
+ * r25: user-level ar.unat
+ * r26: user-level ar.pfs
+ * r27: user-level ar.rsc
+ * r28: user-level ip
+ * r29: user-level psr
+ * r30: user-level cfm
+ * r31: user-level pr
+ * f6-f11: cleared
+ * pr: restored (user-level pr)
+ * b0: restored (user-level rp)
+ * b6: restored
+ * b7: set to __kernel_syscall_via_epc
+ * ar.unat: restored (user-level ar.unat)
+ * ar.pfs: restored (user-level ar.pfs)
+ * ar.rsc: restored (user-level ar.rsc)
+ * ar.rnat: restored (user-level ar.rnat)
+ * ar.bspstore: restored (user-level ar.bspstore)
+ * ar.fpsr: restored (user-level ar.fpsr)
+ * ar.ccv: cleared
+ * ar.csd: cleared
+ * ar.ssd: cleared
+ */
+#ifdef CONFIG_XEN
+GLOBAL_ENTRY(xen_leave_syscall)
+ BR_IF_NATIVE(__ia64_leave_syscall, r22, p7)
+#else
+ENTRY(ia64_leave_syscall)
+#endif
+ PT_REGS_UNWIND_INFO(0)
+ /*
+ * work.need_resched etc. mustn't get changed by this CPU before it returns to
+ * user- or fsys-mode, hence we disable interrupts early on.
+ *
+ * p6 controls whether current_thread_info()->flags needs to be check for
+ * extra work. We always check for extra work when returning to user-level.
+ * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
+ * is 0. After extra work processing has been completed, execution
+ * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
+ * needs to be redone.
+ */
+#ifdef CONFIG_PREEMPT
+ rsm psr.i // disable interrupts
+ cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+ ;;
+ .pred.rel.mutex pUStk,pKStk
+(pKStk) ld4 r21=[r20] // r21 <- preempt_count
+(pUStk) mov r21=0 // r21 <- 0
+ ;;
+ cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
+#else /* !CONFIG_PREEMPT */
+#ifdef CONFIG_XEN
+ movl r2=XSI_PSR_I_ADDR
+ mov r18=1
+ ;;
+ ld8 r2=[r2]
+ ;;
+(pUStk) st1 [r2]=r18
+#else
+(pUStk) rsm psr.i
+#endif
+ cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
+(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
+#endif
+#ifdef CONFIG_XEN
+.global xen_work_processed_syscall;
+xen_work_processed_syscall:
+#else
+.work_processed_syscall:
+#endif
+ adds r2=PT(LOADRS)+16,r12
+ adds r3=PT(AR_BSPSTORE)+16,r12
+ adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
+ ;;
+(p6) ld4 r31=[r18] // load current_thread_info()->flags
+ ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
+ nop.i 0
+ ;;
+ mov r16=ar.bsp // M2 get existing backing store pointer
+ ld8 r18=[r2],PT(R9)-PT(B6) // load b6
+(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
+ ;;
+ ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage)
+(p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending?
+(p6) br.cond.spnt .work_pending_syscall
+ ;;
+ // start restoring the state saved on the kernel stack (struct pt_regs):
+ ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
+ ld8 r11=[r3],PT(CR_IIP)-PT(R11)
+(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE!
+ ;;
+ invala // M0|1 invalidate ALAT
+#ifdef CONFIG_XEN
+ movl r28=XSI_PSR_I_ADDR
+ movl r29=XSI_PSR_IC
+ ;;
+ ld8 r28=[r28]
+ mov r30=1
+ ;;
+ st1 [r28]=r30
+ st4 [r29]=r0 // note: clears both vpsr.i and vpsr.ic!
+ ;;
+#else
+ rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection
+#endif
+ cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs
+
+ ld8 r29=[r2],16 // M0|1 load cr.ipsr
+ ld8 r28=[r3],16 // M0|1 load cr.iip
+ mov r22=r0 // A clear r22
+ ;;
+ ld8 r30=[r2],16 // M0|1 load cr.ifs
+ ld8 r25=[r3],16 // M0|1 load ar.unat
+(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+ ;;
+ ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
+#ifdef CONFIG_XEN
+(pKStk) mov r21=r8
+(pKStk) XEN_HYPER_GET_PSR
+ ;;
+(pKStk) mov r22=r8
+(pKStk) mov r8=r21
+ ;;
+#else
+(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
+#endif
+ nop 0
+ ;;
+ ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0
+ ld8 r27=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc
+ mov f6=f0 // F clear f6
+ ;;
+ ld8 r24=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage)
+ ld8 r31=[r3],PT(R1)-PT(PR) // M0|1 load predicates
+ mov f7=f0 // F clear f7
+ ;;
+ ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr
+ ld8.fill r1=[r3],16 // M0|1 load r1
+(pUStk) mov r17=1 // A
+ ;;
+(pUStk) st1 [r14]=r17 // M2|3
+ ld8.fill r13=[r3],16 // M0|1
+ mov f8=f0 // F clear f8
+ ;;
+ ld8.fill r12=[r2] // M0|1 restore r12 (sp)
+ ld8.fill r15=[r3] // M0|1 restore r15
+ mov b6=r18 // I0 restore b6
+
+ LOAD_PHYS_STACK_REG_SIZE(r17)
+ mov f9=f0 // F clear f9
+(pKStk) br.cond.dpnt.many skip_rbs_switch // B
+
+ srlz.d // M0 ensure interruption collection is off (for cover)
+ shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition
+#ifdef CONFIG_XEN
+ XEN_HYPER_COVER;
+#else
+ cover // B add current frame into dirty partition & set cr.ifs
+#endif
+ ;;
+ mov r19=ar.bsp // M2 get new backing store pointer
+ mov f10=f0 // F clear f10
+
+ nop.m 0
+ movl r14=__kernel_syscall_via_epc // X
+ ;;
+ mov.m ar.csd=r0 // M2 clear ar.csd
+ mov.m ar.ccv=r0 // M2 clear ar.ccv
+ mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc)
+
+ mov.m ar.ssd=r0 // M2 clear ar.ssd
+ mov f11=f0 // F clear f11
+ br.cond.sptk.many rbs_switch // B
+#ifdef CONFIG_XEN
+END(xen_leave_syscall)
+#else
+END(ia64_leave_syscall)
+#endif
+
+#ifdef CONFIG_XEN
+GLOBAL_ENTRY(xen_leave_kernel)
+ BR_IF_NATIVE(__ia64_leave_kernel, r22, p7)
+#else
+GLOBAL_ENTRY(ia64_leave_kernel)
+#endif
+ PT_REGS_UNWIND_INFO(0)
+ /*
+ * work.need_resched etc. mustn't get changed by this CPU before it returns to
+ * user- or fsys-mode, hence we disable interrupts early on.
+ *
+ * p6 controls whether current_thread_info()->flags needs to be check for
+ * extra work. We always check for extra work when returning to user-level.
+ * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
+ * is 0. After extra work processing has been completed, execution
+ * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
+ * needs to be redone.
+ */
+#ifdef CONFIG_PREEMPT
+ rsm psr.i // disable interrupts
+ cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+ ;;
+ .pred.rel.mutex pUStk,pKStk
+(pKStk) ld4 r21=[r20] // r21 <- preempt_count
+(pUStk) mov r21=0 // r21 <- 0
+ ;;
+ cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0)
+#else
+#ifdef CONFIG_XEN
+(pUStk) movl r17=XSI_PSR_I_ADDR
+(pUStk) mov r31=1
+ ;;
+(pUStk) ld8 r17=[r17]
+ ;;
+(pUStk) st1 [r17]=r31
+ ;;
+#else
+(pUStk) rsm psr.i
+#endif
+ cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel
+(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
+#endif
+.work_processed_kernel:
+ adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+ ;;
+(p6) ld4 r31=[r17] // load current_thread_info()->flags
+ adds r21=PT(PR)+16,r12
+ ;;
+
+ lfetch [r21],PT(CR_IPSR)-PT(PR)
+ adds r2=PT(B6)+16,r12
+ adds r3=PT(R16)+16,r12
+ ;;
+ lfetch [r21]
+ ld8 r28=[r2],8 // load b6
+ adds r29=PT(R24)+16,r12
+
+ ld8.fill r16=[r3],PT(AR_CSD)-PT(R16)
+ adds r30=PT(AR_CCV)+16,r12
+(p6) and r19=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
+ ;;
+ ld8.fill r24=[r29]
+ ld8 r15=[r30] // load ar.ccv
+(p6) cmp4.ne.unc p6,p0=r19, r0 // any special work pending?
+ ;;
+ ld8 r29=[r2],16 // load b7
+ ld8 r30=[r3],16 // load ar.csd
+(p6) br.cond.spnt .work_pending
+ ;;
+ ld8 r31=[r2],16 // load ar.ssd
+ ld8.fill r8=[r3],16
+ ;;
+ ld8.fill r9=[r2],16
+ ld8.fill r10=[r3],PT(R17)-PT(R10)
+ ;;
+ ld8.fill r11=[r2],PT(R18)-PT(R11)
+ ld8.fill r17=[r3],16
+ ;;
+ ld8.fill r18=[r2],16
+ ld8.fill r19=[r3],16
+ ;;
+ ld8.fill r20=[r2],16
+ ld8.fill r21=[r3],16
+ mov ar.csd=r30
+ mov ar.ssd=r31
+ ;;
+#ifdef CONFIG_XEN
+ movl r23=XSI_PSR_I_ADDR
+ movl r22=XSI_PSR_IC
+ ;;
+ ld8 r23=[r23]
+ mov r25=1
+ ;;
+ st1 [r23]=r25
+ st4 [r22]=r0 // note: clears both vpsr.i and vpsr.ic!
+ ;;
+#else
+ rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection
+#endif
+ invala // invalidate ALAT
+ ;;
+ ld8.fill r22=[r2],24
+ ld8.fill r23=[r3],24
+ mov b6=r28
+ ;;
+ ld8.fill r25=[r2],16
+ ld8.fill r26=[r3],16
+ mov b7=r29
+ ;;
+ ld8.fill r27=[r2],16
+ ld8.fill r28=[r3],16
+ ;;
+ ld8.fill r29=[r2],16
+ ld8.fill r30=[r3],24
+ ;;
+ ld8.fill r31=[r2],PT(F9)-PT(R31)
+ adds r3=PT(F10)-PT(F6),r3
+ ;;
+ ldf.fill f9=[r2],PT(F6)-PT(F9)
+ ldf.fill f10=[r3],PT(F8)-PT(F10)
+ ;;
+ ldf.fill f6=[r2],PT(F7)-PT(F6)
+ ;;
+ ldf.fill f7=[r2],PT(F11)-PT(F7)
+ ldf.fill f8=[r3],32
+ ;;
+ srlz.d // ensure that inter. collection is off (VHPT is don't care, since text is pinned)
+ mov ar.ccv=r15
+ ;;
+ ldf.fill f11=[r2]
+#ifdef CONFIG_XEN
+ ;;
+ // r16-r31 all now hold bank1 values
+ mov r15=ar.unat
+ movl r2=XSI_BANK1_R16
+ movl r3=XSI_BANK1_R16+8
+ ;;
+.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
+ ;;
+.mem.offset 0,0; st8.spill [r2]=r22,16
+.mem.offset 8,0; st8.spill [r3]=r23,16
+ ;;
+.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,16
+ ;;
+ mov r3=ar.unat
+ movl r2=XSI_B1NAT
+ ;;
+ st8 [r2]=r3
+ mov ar.unat=r15
+ movl r2=XSI_BANKNUM;;
+ st4 [r2]=r0;
+#else
+ bsw.0 // switch back to bank 0 (no stop bit required beforehand...)
+#endif
+ ;;
+(pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency)
+ adds r16=PT(CR_IPSR)+16,r12
+ adds r17=PT(CR_IIP)+16,r12
+
+#ifdef CONFIG_XEN
+(pKStk) mov r29=r8
+(pKStk) XEN_HYPER_GET_PSR
+ ;;
+(pKStk) mov r22=r8
+(pKStk) mov r8=r29
+ ;;
+#else
+(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
+#endif
+ nop.i 0
+ nop.i 0
+ ;;
+ ld8 r29=[r16],16 // load cr.ipsr
+ ld8 r28=[r17],16 // load cr.iip
+ ;;
+ ld8 r30=[r16],16 // load cr.ifs
+ ld8 r25=[r17],16 // load ar.unat
+ ;;
+ ld8 r26=[r16],16 // load ar.pfs
+ ld8 r27=[r17],16 // load ar.rsc
+ cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs
+ ;;
+ ld8 r24=[r16],16 // load ar.rnat (may be garbage)
+ ld8 r23=[r17],16 // load ar.bspstore (may be garbage)
+ ;;
+ ld8 r31=[r16],16 // load predicates
+ ld8 r21=[r17],16 // load b0
+ ;;
+ ld8 r19=[r16],16 // load ar.rsc value for "loadrs"
+ ld8.fill r1=[r17],16 // load r1
+ ;;
+ ld8.fill r12=[r16],16
+ ld8.fill r13=[r17],16
+(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
+ ;;
+ ld8 r20=[r16],16 // ar.fpsr
+ ld8.fill r15=[r17],16
+ ;;
+ ld8.fill r14=[r16],16
+ ld8.fill r2=[r17]
+(pUStk) mov r17=1
+ ;;
+ ld8.fill r3=[r16]
+(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack
+ shr.u r18=r19,16 // get byte size of existing "dirty" partition
+ ;;
+ mov r16=ar.bsp // get existing backing store pointer
+ LOAD_PHYS_STACK_REG_SIZE(r17)
+(pKStk) br.cond.dpnt skip_rbs_switch
+
+ /*
+ * Restore user backing store.
+ *
+ * NOTE: alloc, loadrs, and cover can't be predicated.
+ */
+(pNonSys) br.cond.dpnt dont_preserve_current_frame
+
+#ifdef CONFIG_XEN
+ XEN_HYPER_COVER;
+#else
+ cover // add current frame into dirty partition and set cr.ifs
+#endif
+ ;;
+ mov r19=ar.bsp // get new backing store pointer
+rbs_switch:
+ sub r16=r16,r18 // krbs = old bsp - size of dirty partition
+ cmp.ne p9,p0=r0,r0 // clear p9 to skip restore of cr.ifs
+ ;;
+ sub r19=r19,r16 // calculate total byte size of dirty partition
+ add r18=64,r18 // don't force in0-in7 into memory...
+ ;;
+ shl r19=r19,16 // shift size of dirty partition into loadrs position
+ ;;
+dont_preserve_current_frame:
+ /*
+ * To prevent leaking bits between the kernel and user-space,
+ * we must clear the stacked registers in the "invalid" partition here.
+ * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium,
+ * 5 registers/cycle on McKinley).
+ */
+# define pRecurse p6
+# define pReturn p7
+#ifdef CONFIG_ITANIUM
+# define Nregs 10
+#else
+# define Nregs 14
+#endif
+ alloc loc0=ar.pfs,2,Nregs-2,2,0
+ shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
+ sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize
+ ;;
+ mov ar.rsc=r19 // load ar.rsc to be used for "loadrs"
+ shladd in0=loc1,3,r17
+ mov in1=0
+ ;;
+ TEXT_ALIGN(32)
+rse_clear_invalid:
+#ifdef CONFIG_ITANIUM
+ // cycle 0
+ { .mii
+ alloc loc0=ar.pfs,2,Nregs-2,2,0
+ cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse
+ add out0=-Nregs*8,in0
+}{ .mfb
+ add out1=1,in1 // increment recursion count
+ nop.f 0
+ nop.b 0 // can't do br.call here because of alloc (WAW on CFM)
+ ;;
+}{ .mfi // cycle 1
+ mov loc1=0
+ nop.f 0
+ mov loc2=0
+}{ .mib
+ mov loc3=0
+ mov loc4=0
+(pRecurse) br.call.sptk.many b0=rse_clear_invalid
+
+}{ .mfi // cycle 2
+ mov loc5=0
+ nop.f 0
+ cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
+}{ .mib
+ mov loc6=0
+ mov loc7=0
+(pReturn) br.ret.sptk.many b0
+}
+#else /* !CONFIG_ITANIUM */
+ alloc loc0=ar.pfs,2,Nregs-2,2,0
+ cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse
+ add out0=-Nregs*8,in0
+ add out1=1,in1 // increment recursion count
+ mov loc1=0
+ mov loc2=0
+ ;;
+ mov loc3=0
+ mov loc4=0
+ mov loc5=0
+ mov loc6=0
+ mov loc7=0
+(pRecurse) br.call.dptk.few b0=rse_clear_invalid
+ ;;
+ mov loc8=0
+ mov loc9=0
+ cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
+ mov loc10=0
+ mov loc11=0
+(pReturn) br.ret.dptk.many b0
+#endif /* !CONFIG_ITANIUM */
+# undef pRecurse
+# undef pReturn
+ ;;
+ alloc r17=ar.pfs,0,0,0,0 // drop current register frame
+ ;;
+ loadrs
+ ;;
+skip_rbs_switch:
+ mov ar.unat=r25 // M2
+(pKStk) extr.u r22=r22,21,1 // I0 extract current value of psr.pp from r22
+(pLvSys)mov r19=r0 // A clear r19 for leave_syscall, no-op otherwise
+ ;;
+(pUStk) mov ar.bspstore=r23 // M2
+(pKStk) dep r29=r22,r29,21,1 // I0 update ipsr.pp with psr.pp
+(pLvSys)mov r16=r0 // A clear r16 for leave_syscall, no-op otherwise
+ ;;
+#ifdef CONFIG_XEN
+ movl r25=XSI_IPSR
+ ;;
+ st8[r25]=r29,XSI_IFS_OFS-XSI_IPSR_OFS
+ ;;
+#else
+ mov cr.ipsr=r29 // M2
+#endif
+ mov ar.pfs=r26 // I0
+(pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise
+
+#ifdef CONFIG_XEN
+(p9) st8 [r25]=r30
+ ;;
+ adds r25=XSI_IIP_OFS-XSI_IFS_OFS,r25
+ ;;
+#else
+(p9) mov cr.ifs=r30 // M2
+#endif
+ mov b0=r21 // I0
+(pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise
+
+ mov ar.fpsr=r20 // M2
+#ifdef CONFIG_XEN
+ st8 [r25]=r28
+#else
+ mov cr.iip=r28 // M2
+#endif
+ nop 0
+ ;;
+(pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode
+ nop 0
+(pLvSys)mov r2=r0
+
+ mov ar.rsc=r27 // M2
+ mov pr=r31,-1 // I0
+#ifdef CONFIG_XEN
+ ;;
+ XEN_HYPER_RFI;
+#else
+ rfi // B
+#endif
+
+ /*
+ * On entry:
+ * r20 = ¤t->thread_info->pre_count (if CONFIG_PREEMPT)
+ * r31 = current->thread_info->flags
+ * On exit:
+ * p6 = TRUE if work-pending-check needs to be redone
+ */
+.work_pending_syscall:
+ add r2=-8,r2
+ add r3=-8,r3
+ ;;
+ st8 [r2]=r8
+ st8 [r3]=r10
+.work_pending:
+ tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0?
+(p6) br.cond.sptk.few .notify
+#ifdef CONFIG_PREEMPT
+(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
+ ;;
+(pKStk) st4 [r20]=r21
+ ssm psr.i // enable interrupts
+#endif
+ br.call.spnt.many rp=schedule
+.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1
+#ifdef CONFIG_XEN
+ movl r2=XSI_PSR_I_ADDR
+ mov r20=1
+ ;;
+ ld8 r2=[r2]
+ ;;
+ st1 [r2]=r20
+#else
+ rsm psr.i // disable interrupts
+#endif
+ ;;
+#ifdef CONFIG_PREEMPT
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+ ;;
+(pKStk) st4 [r20]=r0 // preempt_count() <- 0
+#endif
+(pLvSys)br.cond.sptk.few .work_pending_syscall_end
+ br.cond.sptk.many .work_processed_kernel // re-check
+
+.notify:
+(pUStk) br.call.spnt.many rp=notify_resume_user
+.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0
+(pLvSys)br.cond.sptk.few .work_pending_syscall_end
+ br.cond.sptk.many .work_processed_kernel // don't re-check
+
+.work_pending_syscall_end:
+ adds r2=PT(R8)+16,r12
+ adds r3=PT(R10)+16,r12
+ ;;
+ ld8 r8=[r2]
+ ld8 r10=[r3]
+#ifdef CONFIG_XEN
+ br.cond.sptk.many xen_work_processed_syscall // re-check
+#else
+ br.cond.sptk.many .work_processed_syscall // re-check
+#endif
+
+#ifdef CONFIG_XEN
+END(xen_leave_kernel)
+#else
+END(ia64_leave_kernel)
+#endif
diff --git a/arch/ia64/xen/xenivt.S b/arch/ia64/xen/xenivt.S
new file mode 100644
index 0000000..f2eaa1f
--- /dev/null
+++ b/arch/ia64/xen/xenivt.S
@@ -0,0 +1,2204 @@
+/*
+ * arch/ia64/xen/ivt.S
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ * Dan Magenheimer <dan.magenheimer@hp.com>
+ */
+/*
+ * This file defines the interruption vector table used by the CPU.
+ * It does not include one entry per possible cause of interruption.
+ *
+ * The first 20 entries of the table contain 64 bundles each while the
+ * remaining 48 entries contain only 16 bundles each.
+ *
+ * The 64 bundles are used to allow inlining the whole handler for critical
+ * interruptions like TLB misses.
+ *
+ * For each entry, the comment is as follows:
+ *
+ * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ * entry offset ----/ / / / /
+ * entry number ---------/ / / /
+ * size of the entry -------------/ / /
+ * vector name -------------------------------------/ /
+ * interruptions triggering this vector ----------------------/
+ *
+ * The table is 32KB in size and must be aligned on 32KB boundary.
+ * (The CPU ignores the 15 lower bits of the address)
+ *
+ * Table is based upon EAS2.6 (Oct 1999)
+ */
+
+
+#include <asm/asmmacro.h>
+#include <asm/break.h>
+#include <asm/ia32.h>
+#include <asm/kregs.h>
+#include <asm/asm-offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+
+#ifdef CONFIG_XEN
+#define ia64_ivt xen_ivt
+#endif
+
+#if 1
+# define PSR_DEFAULT_BITS psr.ac
+#else
+# define PSR_DEFAULT_BITS 0
+#endif
+
+#if 0
+ /*
+ * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't
+ * needed for something else before enabling this...
+ */
+# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16
+#else
+# define DBG_FAULT(i)
+#endif
+
+#ifdef CONFIG_XEN
+#include "xenminstate.h"
+#else
+#include "minstate.h"
+#endif
+
+#define FAULT(n) \
+ mov r31=pr; \
+ mov r19=n;; /* prepare to save predicates */ \
+ br.sptk.many dispatch_to_fault_handler
+
+ .section .text.ivt,"ax"
+
+ .align 32768 // align on 32KB boundary
+ .global ia64_ivt
+ia64_ivt:
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
+ENTRY(vhpt_miss)
+ DBG_FAULT(0)
+ /*
+ * The VHPT vector is invoked when the TLB entry for the virtual page table
+ * is missing. This happens only as a result of a previous
+ * (the "original") TLB miss, which may either be caused by an instruction
+ * fetch or a data access (or non-access).
+ *
+ * What we do here is normal TLB miss handing for the _original_ miss,
+ * followed by inserting the TLB entry for the virtual page table page
+ * that the VHPT walker was attempting to access. The latter gets
+ * inserted as long as page table entry above pte level have valid
+ * mappings for the faulting address. The TLB entry for the original
+ * miss gets inserted only if the pte entry indicates that the page is
+ * present.
+ *
+ * do_page_fault gets invoked in the following cases:
+ * - the faulting virtual address uses unimplemented address bits
+ * - the faulting virtual address has no valid page table mapping
+ */
+#ifdef CONFIG_XEN
+ movl r16=XSI_IFA
+ ;;
+ ld8 r16=[r16]
+#ifdef CONFIG_HUGETLB_PAGE
+ movl r18=PAGE_SHIFT
+ movl r25=XSI_ITIR
+ ;;
+ ld8 r25=[r25]
+#endif
+#else
+ mov r16=cr.ifa // get address that caused the TLB miss
+#ifdef CONFIG_HUGETLB_PAGE
+ movl r18=PAGE_SHIFT
+ mov r25=cr.itir
+#endif
+#endif
+ ;;
+#ifdef CONFIG_XEN
+ XEN_HYPER_RSM_PSR_DT;
+#else
+ rsm psr.dt // use physical addressing for data
+#endif
+ mov r31=pr // save the predicate registers
+ mov r19=IA64_KR(PT_BASE) // get page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+ shr.u r17=r16,61 // get the region number into r17
+ ;;
+ shr.u r22=r21,3
+#ifdef CONFIG_HUGETLB_PAGE
+ extr.u r26=r25,2,6
+ ;;
+ cmp.ne p8,p0=r18,r26
+ sub r27=r26,r18
+ ;;
+(p8) dep r25=r18,r25,2,6
+(p8) shr r22=r22,r27
+#endif
+ ;;
+ cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
+ shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
+ ;;
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r28=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
+#ifdef CONFIG_PGTABLE_4
+ dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
+ ;;
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+(p7) ld8 r29=[r28] // get *pud (may be 0)
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) == NULL?
+ dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
+#else
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
+#endif
+ ;;
+(p7) ld8 r20=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) == NULL?
+ dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
+ ;;
+(p7) ld8 r18=[r21] // read *pte
+#ifdef CONFIG_XEN
+ movl r19=XSI_ISR
+ ;;
+ ld8 r19=[r19]
+#else
+ mov r19=cr.isr // cr.isr bit 32 tells us if this is an insn miss
+#endif
+ ;;
+(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
+#ifdef CONFIG_XEN
+ movl r22=XSI_IHA
+ ;;
+ ld8 r22=[r22]
+#else
+ mov r22=cr.iha // get the VHPT address that caused the TLB miss
+#endif
+ ;; // avoid RAW on p7
+(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss?
+ dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address
+ ;;
+#ifdef CONFIG_XEN
+ mov r24=r8
+ mov r8=r18
+ ;;
+(p10) XEN_HYPER_ITC_I
+ ;;
+(p11) XEN_HYPER_ITC_D
+ ;;
+ mov r8=r24
+ ;;
+#else
+(p10) itc.i r18 // insert the instruction TLB entry
+(p11) itc.d r18 // insert the data TLB entry
+#endif
+(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
+#ifdef CONFIG_XEN
+ movl r24=XSI_IFA
+ ;;
+ st8 [r24]=r22
+ ;;
+#ifdef CONFIG_HUGETLB_PAGE
+(p8) movl r24=XSI_ITIR
+ ;;
+(p8) st8 [r24]=r25
+#endif
+#else
+ mov cr.ifa=r22
+
+#ifdef CONFIG_HUGETLB_PAGE
+(p8) mov cr.itir=r25 // change to default page-size for VHPT
+#endif
+#endif
+
+ /*
+ * Now compute and insert the TLB entry for the virtual page table. We never
+ * execute in a page table page so there is no need to set the exception deferral
+ * bit.
+ */
+ adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23
+ ;;
+#ifdef CONFIG_XEN
+(p7) mov r25=r8
+(p7) mov r8=r24
+ ;;
+(p7) XEN_HYPER_ITC_D
+ ;;
+(p7) mov r8=r25
+ ;;
+#else
+(p7) itc.d r24
+#endif
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ /*
+ * Re-check pagetable entry. If they changed, we may have received a ptc.g
+ * between reading the pagetable and the "itc". If so, flush the entry we
+ * inserted and retry. At this point, we have:
+ *
+ * r28 = equivalent of pud_offset(pgd, ifa)
+ * r17 = equivalent of pmd_offset(pud, ifa)
+ * r21 = equivalent of pte_offset(pmd, ifa)
+ *
+ * r29 = *pud
+ * r20 = *pmd
+ * r18 = *pte
+ */
+ ld8 r25=[r21] // read *pte again
+ ld8 r26=[r17] // read *pmd again
+#ifdef CONFIG_PGTABLE_4
+ ld8 r19=[r28] // read *pud again
+#endif
+ cmp.ne p6,p7=r0,r0
+ ;;
+ cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
+#ifdef CONFIG_PGTABLE_4
+ cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
+#endif
+ mov r27=PAGE_SHIFT<<2
+ ;;
+(p6) ptc.l r22,r27 // purge PTE page translation
+(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
+ ;;
+(p6) ptc.l r16,r27 // purge translation
+#endif
+
+ mov pr=r31,-1 // restore predicate registers
+#ifdef CONFIG_XEN
+ XEN_HYPER_RFI
+ dv_serialize_data
+#else
+ rfi
+#endif
+END(vhpt_miss)
+
+ .org ia64_ivt+0x400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
+ENTRY(itlb_miss)
+ DBG_FAULT(1)
+ /*
+ * The ITLB handler accesses the PTE via the virtually mapped linear
+ * page table. If a nested TLB miss occurs, we switch into physical
+ * mode, walk the page table, and then re-execute the PTE read and
+ * go on normally after that.
+ */
+#ifdef CONFIG_XEN
+ movl r16=XSI_IFA
+ ;;
+ ld8 r16=[r16]
+#else
+ mov r16=cr.ifa // get virtual address
+#endif
+ mov r29=b0 // save b0
+ mov r31=pr // save predicates
+.itlb_fault:
+#ifdef CONFIG_XEN
+ movl r17=XSI_IHA
+ ;;
+ ld8 r17=[r17] // get virtual address of L3 PTE
+#else
+ mov r17=cr.iha // get virtual address of PTE
+#endif
+ movl r30=1f // load nested fault continuation point
+ ;;
+1: ld8 r18=[r17] // read *pte
+ ;;
+ mov b0=r29
+ tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
+(p6) br.cond.spnt page_fault
+ ;;
+#ifdef CONFIG_XEN
+ mov r19=r8
+ mov r8=r18
+ ;;
+ XEN_HYPER_ITC_I
+ ;;
+ mov r8=r19
+#else
+ itc.i r18
+#endif
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+#ifdef CONFIG_XEN
+ XEN_HYPER_RFI
+ dv_serialize_data
+#else
+ rfi
+#endif
+END(itlb_miss)
+
+ .org ia64_ivt+0x0800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
+ENTRY(dtlb_miss)
+ DBG_FAULT(2)
+ /*
+ * The DTLB handler accesses the PTE via the virtually mapped linear
+ * page table. If a nested TLB miss occurs, we switch into physical
+ * mode, walk the page table, and then re-execute the PTE read and
+ * go on normally after that.
+ */
+#ifdef CONFIG_XEN
+ movl r16=XSI_IFA
+ ;;
+ ld8 r16=[r16]
+#else
+ mov r16=cr.ifa // get virtual address
+#endif
+ mov r29=b0 // save b0
+ mov r31=pr // save predicates
+dtlb_fault:
+#ifdef CONFIG_XEN
+ movl r17=XSI_IHA
+ ;;
+ ld8 r17=[r17] // get virtual address of L3 PTE
+#else
+ mov r17=cr.iha // get virtual address of PTE
+#endif
+ movl r30=1f // load nested fault continuation point
+ ;;
+1: ld8 r18=[r17] // read *pte
+ ;;
+ mov b0=r29
+ tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
+(p6) br.cond.spnt page_fault
+ ;;
+#ifdef CONFIG_XEN
+ mov r19=r8
+ mov r8=r18
+ ;;
+ XEN_HYPER_ITC_D
+ ;;
+ mov r8=r19
+ ;;
+#else
+ itc.d r18
+#endif
+ ;;
+#ifdef CONFIG_SMP
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r19=[r17] // read *pte again and see if same
+ mov r20=PAGE_SHIFT<<2 // setup page size for purge
+ ;;
+ cmp.ne p7,p0=r18,r19
+ ;;
+(p7) ptc.l r16,r20
+#endif
+ mov pr=r31,-1
+#ifdef CONFIG_XEN
+ XEN_HYPER_RFI
+ dv_serialize_data
+#else
+ rfi
+#endif
+END(dtlb_miss)
+
+ .org ia64_ivt+0x0c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
+ENTRY(alt_itlb_miss)
+ DBG_FAULT(3)
+#ifdef CONFIG_XEN
+ movl r31=XSI_IPSR
+ ;;
+ ld8 r21=[r31],XSI_IFA_OFS-XSI_IPSR_OFS // get ipsr, point to ifa
+ movl r17=PAGE_KERNEL
+ ;;
+ ld8 r16=[r31] // get ifa
+#else
+ mov r16=cr.ifa // get address that caused the TLB miss
+ movl r17=PAGE_KERNEL
+ mov r21=cr.ipsr
+#endif
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ mov r31=pr
+ ;;
+#ifdef CONFIG_DISABLE_VHPT
+ shr.u r22=r16,61 // get the region number into r21
+ ;;
+ cmp.gt p8,p0=6,r22 // user mode
+ ;;
+#ifdef CONFIG_XEN
+ //XXX notyet
+#else
+(p8) thash r17=r16
+ ;;
+(p8) mov cr.iha=r17
+#endif
+(p8) mov r29=b0 // save b0
+(p8) br.cond.dptk .itlb_fault
+#endif
+ extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
+ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
+ shr.u r18=r16,57 // move address bit 61 to bit 4
+ ;;
+ andcm r18=0x10,r18 // bit 4=~address-bit(61)
+ cmp.ne p8,p0=r0,r23 // psr.cpl != 0?
+ or r19=r17,r19 // insert PTE control bits into r19
+ ;;
+ or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
+(p8) br.cond.spnt page_fault
+ ;;
+#ifdef CONFIG_XEN
+ mov r18=r8
+ mov r8=r19
+ ;;
+ XEN_HYPER_ITC_I
+ ;;
+ mov r8=r18
+ ;;
+ mov pr=r31,-1
+ ;;
+ XEN_HYPER_RFI;
+#else
+ itc.i r19 // insert the TLB entry
+ mov pr=r31,-1
+ rfi
+#endif
+END(alt_itlb_miss)
+
+ .org ia64_ivt+0x1000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
+ENTRY(alt_dtlb_miss)
+ DBG_FAULT(4)
+#ifdef CONFIG_XEN
+ movl r31=XSI_IPSR
+ ;;
+ ld8 r21=[r31],XSI_ISR_OFS-XSI_IPSR_OFS // get ipsr, point to isr
+ movl r17=PAGE_KERNEL
+ ;;
+ ld8 r20=[r31],XSI_IFA_OFS-XSI_ISR_OFS // get isr, point to ifa
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ ;;
+ ld8 r16=[r31] // get ifa
+#else
+ mov r16=cr.ifa // get address that caused the TLB miss
+ movl r17=PAGE_KERNEL
+ mov r20=cr.isr
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ mov r21=cr.ipsr
+#endif
+ mov r31=pr
+ mov r24=PERCPU_ADDR
+ ;;
+#ifdef CONFIG_DISABLE_VHPT
+ shr.u r22=r16,61 // get the region number into r21
+ ;;
+ cmp.gt p8,p0=6,r22 // access to region 0-5
+ ;;
+#ifdef CONFIG_XEN
+ //XXX notyet
+#else
+(p8) thash r17=r16
+ ;;
+(p8) mov cr.iha=r17
+#endif
+(p8) mov r29=b0 // save b0
+(p8) br.cond.dptk dtlb_fault
+#endif
+ cmp.ge p10,p11=r16,r24 // access to per_cpu_data?
+ tbit.z p12,p0=r16,61 // access to region 6?
+ mov r25=PERCPU_PAGE_SHIFT << 2
+ mov r26=PERCPU_PAGE_SIZE
+ nop.m 0
+ nop.b 0
+ ;;
+(p10) mov r19=IA64_KR(PER_CPU_DATA)
+(p11) and r19=r19,r16 // clear non-ppn fields
+ extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
+ and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field
+ tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
+ tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on?
+ ;;
+(p10) sub r19=r19,r26
+#ifdef CONFIG_XEN
+(p10) movl r24=XSI_ITIR
+ ;;
+(p10) st8 [r24]=r25
+#else
+(p10) mov cr.itir=r25
+#endif
+ cmp.ne p8,p0=r0,r23
+(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field
+(p12) dep r17=-1,r17,4,1 // set ma=UC for region 6 addr
+(p8) br.cond.spnt page_fault
+
+ dep r21=-1,r21,IA64_PSR_ED_BIT,1
+ ;;
+ or r19=r19,r17 // insert PTE control bits into r19
+(p6) mov cr.ipsr=r21
+ ;;
+#ifdef CONFIG_XEN
+(p7) mov r18=r8
+(p7) mov r8=r19
+ ;;
+(p7) XEN_HYPER_ITC_D
+ ;;
+(p7) mov r8=r18
+ ;;
+ mov pr=r31,-1
+ ;;
+ XEN_HYPER_RFI;
+#else
+(p7) itc.d r19 // insert the TLB entry
+ mov pr=r31,-1
+ rfi
+#endif
+END(alt_dtlb_miss)
+
+ .org ia64_ivt+0x1400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
+ENTRY(nested_dtlb_miss)
+ /*
+ * In the absence of kernel bugs, we get here when the virtually mapped linear
+ * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
+ * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page
+ * table is missing, a nested TLB miss fault is triggered and control is
+ * transferred to this point. When this happens, we lookup the pte for the
+ * faulting address by walking the page table in physical mode and return to the
+ * continuation point passed in register r30 (or call page_fault if the address is
+ * not mapped).
+ *
+ * Input: r16: faulting address
+ * r29: saved b0
+ * r30: continuation address
+ * r31: saved pr
+ *
+ * Output: r17: physical address of PTE of faulting address
+ * r29: saved b0
+ * r30: continuation address
+ * r31: saved pr
+ *
+ * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
+ */
+#ifdef CONFIG_XEN
+ XEN_HYPER_RSM_PSR_DT;
+#else
+ rsm psr.dt // switch to using physical data addressing
+#endif
+ mov r19=IA64_KR(PT_BASE) // get the page table base address
+ shl r21=r16,3 // shift bit 60 into sign bit
+#ifdef CONFIG_XEN
+ movl r18=XSI_ITIR
+ ;;
+ ld8 r18=[r18]
+#else
+ mov r18=cr.itir
+#endif
+ ;;
+ shr.u r17=r16,61 // get the region number into r17
+ extr.u r18=r18,2,6 // get the faulting page size
+ ;;
+ cmp.eq p6,p7=5,r17 // is faulting address in region 5?
+ add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
+ add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
+ ;;
+ shr.u r22=r16,r22
+ shr.u r18=r16,r18
+(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
+
+ srlz.d
+ LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir
+
+ .pred.rel "mutex", p6, p7
+(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
+(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
+ ;;
+(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
+(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
+ cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
+#ifdef CONFIG_PGTABLE_4
+ shr.u r18=r22,PUD_SHIFT // shift pud index into position
+#else
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+#endif
+ ;;
+ ld8 r17=[r17] // get *pgd (may be 0)
+ ;;
+(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr)
+ ;;
+#ifdef CONFIG_PGTABLE_4
+(p7) ld8 r17=[r17] // get *pud (may be 0)
+ shr.u r18=r22,PMD_SHIFT // shift pmd index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL?
+ dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
+ ;;
+#endif
+(p7) ld8 r17=[r17] // get *pmd (may be 0)
+ shr.u r19=r22,PAGE_SHIFT // shift pte index into position
+ ;;
+(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL?
+ dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr);
+(p6) br.cond.spnt page_fault
+ mov b0=r30
+ br.sptk.many b0 // return to continuation point
+END(nested_dtlb_miss)
+
+ .org ia64_ivt+0x1800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
+ENTRY(ikey_miss)
+ DBG_FAULT(6)
+ FAULT(6)
+END(ikey_miss)
+
+ //-----------------------------------------------------------------------------------
+ // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address)
+ENTRY(page_fault)
+#ifdef CONFIG_XEN
+ XEN_HYPER_SSM_PSR_DT
+#else
+ ssm psr.dt
+ ;;
+ srlz.i
+#endif
+ ;;
+ SAVE_MIN_WITH_COVER
+ alloc r15=ar.pfs,0,0,3,0
+#ifdef CONFIG_XEN
+ movl r3=XSI_ISR
+ ;;
+ ld8 out1=[r3],XSI_IFA_OFS-XSI_ISR_OFS // get vcr.isr, point to ifa
+ ;;
+ ld8 out0=[r3] // get vcr.ifa
+ mov r14=1
+ ;;
+ add r3=XSI_PSR_IC_OFS-XSI_IFA_OFS, r3 // point to vpsr.ic
+ ;;
+ st4 [r3]=r14 // vpsr.ic = 1
+ adds r3=8,r2 // set up second base pointer
+ ;;
+#else
+ mov out0=cr.ifa
+ mov out1=cr.isr
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collectin is on
+ ;;
+#endif
+#ifdef CONFIG_XEN
+
+#define MASK_TO_PEND_OFS (-1)
+
+(p15) movl r14=XSI_PSR_I_ADDR
+ ;;
+(p15) ld8 r14=[r14]
+ ;;
+(p15) st1 [r14]=r0,MASK_TO_PEND_OFS // if (p15) vpsr.i = 1
+ ;; // if (p15) (vcpu->vcpu_info->evtchn_upcall_mask)=0
+(p15) ld1 r14=[r14] // if (vcpu->vcpu_info->evtchn_upcall_pending)
+ ;;
+(p15) cmp.ne p15,p0=r14,r0
+ ;;
+(p15) XEN_HYPER_SSM_I
+#else
+(p15) ssm psr.i // restore psr.i
+#endif
+ movl r14=ia64_leave_kernel
+ ;;
+ SAVE_REST
+ mov rp=r14
+ ;;
+ adds out2=16,r12 // out2 = pointer to pt_regs
+ br.call.sptk.many b6=ia64_do_page_fault // ignore return address
+END(page_fault)
+
+ .org ia64_ivt+0x1c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
+ENTRY(dkey_miss)
+ DBG_FAULT(7)
+ FAULT(7)
+END(dkey_miss)
+
+ .org ia64_ivt+0x2000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
+ENTRY(dirty_bit)
+ DBG_FAULT(8)
+ /*
+ * What we do here is to simply turn on the dirty bit in the PTE. We need to
+ * update both the page-table and the TLB entry. To efficiently access the PTE,
+ * we address it through the virtual page table. Most likely, the TLB entry for
+ * the relevant virtual page table page is still present in the TLB so we can
+ * normally do this without additional TLB misses. In case the necessary virtual
+ * page table TLB entry isn't present, we take a nested TLB miss hit where we look
+ * up the physical address of the L3 PTE and then continue at label 1 below.
+ */
+#ifdef CONFIG_XEN
+ movl r16=XSI_IFA
+ ;;
+ ld8 r16=[r16]
+ ;;
+#else
+ mov r16=cr.ifa // get the address that caused the fault
+#endif
+ movl r30=1f // load continuation point in case of nested fault
+ ;;
+#ifdef CONFIG_XEN
+ mov r18=r8;
+ mov r8=r16;
+ XEN_HYPER_THASH;;
+ mov r17=r8;
+ mov r8=r18;;
+#else
+ thash r17=r16 // compute virtual address of L3 PTE
+#endif
+ mov r29=b0 // save b0 in case of nested fault
+ mov r31=pr // save pr
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present
+ ;;
+#ifdef CONFIG_XEN
+(p6) mov r18=r8
+(p6) mov r8=r25
+ ;;
+(p6) XEN_HYPER_ITC_D
+ ;;
+(p6) mov r8=r18
+#else
+(p6) itc.d r25 // install updated PTE
+#endif
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.d r18 // install updated PTE
+#endif
+ mov pr=r31,-1 // restore pr
+#ifdef CONFIG_XEN
+ XEN_HYPER_RFI
+ dv_serialize_data
+#else
+ rfi
+#endif
+END(dirty_bit)
+
+ .org ia64_ivt+0x2400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
+ENTRY(iaccess_bit)
+ DBG_FAULT(9)
+ // Like Entry 8, except for instruction access
+#ifdef CONFIG_XEN
+ movl r16=XSI_IFA
+ ;;
+ ld8 r16=[r16]
+ ;;
+#else
+ mov r16=cr.ifa // get the address that caused the fault
+#endif
+ movl r30=1f // load continuation point in case of nested fault
+ mov r31=pr // save predicates
+#ifdef CONFIG_ITANIUM
+ /*
+ * Erratum 10 (IFA may contain incorrect address) has "NoFix" status.
+ */
+ mov r17=cr.ipsr
+ ;;
+ mov r18=cr.iip
+ tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set?
+ ;;
+(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa
+#endif /* CONFIG_ITANIUM */
+ ;;
+#ifdef CONFIG_XEN
+ mov r18=r8;
+ mov r8=r16;
+ XEN_HYPER_THASH;;
+ mov r17=r8;
+ mov r8=r18;;
+#else
+ thash r17=r16 // compute virtual address of L3 PTE
+#endif
+ mov r29=b0 // save b0 in case of nested fault)
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;;
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the accessed bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page present
+ ;;
+#ifdef CONFIG_XEN
+ mov r26=r8
+ mov r8=r25
+ ;;
+(p6) XEN_HYPER_ITC_I
+ ;;
+ mov r8=r26
+ ;;
+#else
+(p6) itc.i r25 // install updated PTE
+#endif
+ ;;
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov b0=r29 // restore b0
+ mov ar.ccv=r28
+#else /* !CONFIG_SMP */
+ ;;
+1: ld8 r18=[r17]
+ ;;
+ or r18=_PAGE_A,r18 // set the accessed bit
+ mov b0=r29 // restore b0
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.i r18 // install updated PTE
+#endif /* !CONFIG_SMP */
+ mov pr=r31,-1
+#ifdef CONFIG_XEN
+ XEN_HYPER_RFI
+ dv_serialize_data
+#else
+ rfi
+#endif
+END(iaccess_bit)
+
+ .org ia64_ivt+0x2800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
+ENTRY(daccess_bit)
+ DBG_FAULT(10)
+ // Like Entry 8, except for data access
+#ifdef CONFIG_XEN
+ movl r16=XSI_IFA
+ ;;
+ ld8 r16=[r16]
+ ;;
+#else
+ mov r16=cr.ifa // get the address that caused the fault
+#endif
+ movl r30=1f // load continuation point in case of nested fault
+ ;;
+#ifdef CONFIG_XEN
+ mov r18=r8
+ mov r8=r16
+ XEN_HYPER_THASH
+ ;;
+ mov r17=r8
+ mov r8=r18
+ ;;
+#else
+ thash r17=r16 // compute virtual address of L3 PTE
+#endif
+ mov r31=pr
+ mov r29=b0 // save b0 in case of nested fault)
+#ifdef CONFIG_SMP
+ mov r28=ar.ccv // save ar.ccv
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ mov ar.ccv=r18 // set compare value for cmpxchg
+ or r25=_PAGE_A,r18 // set the dirty bit
+ tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit
+ ;;
+(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present
+ mov r24=PAGE_SHIFT<<2
+ ;;
+(p6) cmp.eq p6,p7=r26,r18 // Only if page is present
+ ;;
+#ifdef CONFIG_XEN
+ mov r26=r8
+ mov r8=r25
+ ;;
+(p6) XEN_HYPER_ITC_D
+ ;;
+ mov r8=r26
+ ;;
+#else
+(p6) itc.d r25 // install updated PTE
+#endif
+ /*
+ * Tell the assemblers dependency-violation checker that the above "itc" instructions
+ * cannot possibly affect the following loads:
+ */
+ dv_serialize_data
+ ;;
+ ld8 r18=[r17] // read PTE again
+ ;;
+ cmp.eq p6,p7=r18,r25 // is it same as the newly installed
+ ;;
+(p7) ptc.l r16,r24
+ mov ar.ccv=r28
+#else
+ ;;
+1: ld8 r18=[r17]
+ ;; // avoid RAW on r18
+ or r18=_PAGE_A,r18 // set the accessed bit
+ ;;
+ st8 [r17]=r18 // store back updated PTE
+ itc.d r18 // install updated PTE
+#endif
+ mov b0=r29 // restore b0
+ mov pr=r31,-1
+#ifdef CONFIG_XEN
+ XEN_HYPER_RFI
+ dv_serialize_data
+#else
+ rfi
+#endif
+END(daccess_bit)
+
+ .org ia64_ivt+0x2c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
+ENTRY(break_fault)
+ /*
+ * The streamlined system call entry/exit paths only save/restore the initial part
+ * of pt_regs. This implies that the callers of system-calls must adhere to the
+ * normal procedure calling conventions.
+ *
+ * Registers to be saved & restored:
+ * CR registers: cr.ipsr, cr.iip, cr.ifs
+ * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr
+ * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15
+ * Registers to be restored only:
+ * r8-r11: output value from the system call.
+ *
+ * During system call exit, scratch registers (including r15) are modified/cleared
+ * to prevent leaking bits from kernel to user level.
+ */
+ DBG_FAULT(11)
+ mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc)
+#ifdef CONFIG_XEN
+ movl r22=XSI_IPSR
+ ;;
+ ld8 r29=[r22],XSI_IIM_OFS-XSI_IPSR_OFS // get ipsr, point to iip
+#else
+ mov r29=cr.ipsr // M2 (12 cyc)
+#endif
+ mov r31=pr // I0 (2 cyc)
+
+#ifdef CONFIG_XEN
+ ;;
+ ld8 r17=[r22],XSI_IIP_OFS-XSI_IIM_OFS
+#else
+ mov r17=cr.iim // M2 (2 cyc)
+#endif
+ mov.m r27=ar.rsc // M2 (12 cyc)
+ mov r18=__IA64_BREAK_SYSCALL // A
+
+ mov.m ar.rsc=0 // M2
+ mov.m r21=ar.fpsr // M2 (12 cyc)
+ mov r19=b6 // I0 (2 cyc)
+ ;;
+ mov.m r23=ar.bspstore // M2 (12 cyc)
+ mov.m r24=ar.rnat // M2 (5 cyc)
+ mov.i r26=ar.pfs // I0 (2 cyc)
+
+ invala // M0|1
+ nop.m 0 // M
+ mov r20=r1 // A save r1
+
+ nop.m 0
+ movl r30=sys_call_table // X
+
+#ifdef CONFIG_XEN
+ ld8 r28=[r22]
+#else
+ mov r28=cr.iip // M2 (2 cyc)
+#endif
+ cmp.eq p0,p7=r18,r17 // I0 is this a system call?
+(p7) br.cond.spnt non_syscall // B no ->
+ //
+ // From this point on, we are definitely on the syscall-path
+ // and we can use (non-banked) scratch registers.
+ //
+///////////////////////////////////////////////////////////////////////
+ mov r1=r16 // A move task-pointer to "addl"-addressable reg
+ mov r2=r16 // A setup r2 for ia64_syscall_setup
+ add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags
+
+ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16
+ adds r15=-1024,r15 // A subtract 1024 from syscall number
+ mov r3=NR_syscalls - 1
+ ;;
+ ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag
+ ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags
+ extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr
+
+ shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024)
+ addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS
+ cmp.leu p6,p7=r15,r3 // A syscall number in range?
+ ;;
+
+ lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS
+(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point
+ tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT?
+
+ mov.m ar.bspstore=r22 // M2 switch to kernel RBS
+ cmp.eq p8,p9=2,r8 // A isr.ei==2?
+ ;;
+
+(p8) mov r8=0 // A clear ei to 0
+(p7) movl r30=sys_ni_syscall // X
+
+(p8) adds r28=16,r28 // A switch cr.iip to next bundle
+(p9) adds r8=1,r8 // A increment ei to next slot
+ nop.i 0
+ ;;
+
+ mov.m r25=ar.unat // M2 (5 cyc)
+ dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
+ adds r15=1024,r15 // A restore original syscall number
+ //
+ // If any of the above loads miss in L1D, we'll stall here until
+ // the data arrives.
+ //
+///////////////////////////////////////////////////////////////////////
+ st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
+ mov b6=r30 // I0 setup syscall handler branch reg early
+ cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
+
+ and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
+ mov r18=ar.bsp // M2 (12 cyc)
+(pKStk) br.cond.spnt .break_fixup // B we're already in kernel-mode -- fix up RBS
+ ;;
+.back_from_break_fixup:
+(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack
+ cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
+ br.call.sptk.many b7=ia64_syscall_setup // B
+1:
+ mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
+ nop 0
+#ifdef CONFIG_XEN
+ mov r2=b0; br.call.sptk b0=xen_bsw1;; mov b0=r2;;
+#else
+ bsw.1 // B (6 cyc) regs are saved, switch to bank 1
+#endif
+ ;;
+
+#ifdef CONFIG_XEN
+ movl r16=XSI_PSR_IC
+ mov r3=1
+ ;;
+ st4 [r16]=r3,XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS // vpsr.ic = 1
+#else
+ ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection
+#endif
+ movl r3=ia64_ret_from_syscall // X
+ ;;
+
+ srlz.i // M0 ensure interruption collection is on
+ mov rp=r3 // I0 set the real return addr
+(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
+
+#ifdef CONFIG_XEN
+(p15) ld8 r16=[r16] // vpsr.i
+ ;;
+(p15) st1 [r16]=r0,MASK_TO_PEND_OFS // if (p15) vpsr.i = 1
+ ;; // if (p15) (vcpu->vcpu_info->evtchn_upcall_mask)=0
+(p15) ld1 r2=[r16] // if (vcpu->vcpu_info->evtchn_upcall_pending)
+ ;;
+(p15) cmp.ne.unc p6,p0=r2,r0
+ ;;
+(p6) XEN_HYPER_SSM_I // do a real ssm psr.i
+#else
+(p15) ssm psr.i // M2 restore psr.i
+#endif
+(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr)
+ br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic
+ // NOT REACHED
+///////////////////////////////////////////////////////////////////////
+ // On entry, we optimistically assumed that we're coming from user-space.
+ // For the rare cases where a system-call is done from within the kernel,
+ // we fix things up at this point:
+.break_fixup:
+ add r1=-IA64_PT_REGS_SIZE,sp // A allocate space for pt_regs structure
+ mov ar.rnat=r24 // M2 restore kernel's AR.RNAT
+ ;;
+ mov ar.bspstore=r23 // M2 restore kernel's AR.BSPSTORE
+ br.cond.sptk .back_from_break_fixup
+END(break_fault)
+
+ .org ia64_ivt+0x3000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
+ENTRY(interrupt)
+ DBG_FAULT(12)
+ mov r31=pr // prepare to save predicates
+ ;;
+ SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
+#ifdef CONFIG_XEN
+ movl r3=XSI_PSR_IC
+ mov r14=1
+ ;;
+ st4 [r3]=r14
+#else
+ ssm psr.ic | PSR_DEFAULT_BITS
+#endif
+ ;;
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ srlz.i // ensure everybody knows psr.ic is back on
+ ;;
+ SAVE_REST
+ ;;
+ MCA_RECOVER_RANGE(interrupt)
+ alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group
+#ifdef CONFIG_XEN
+ ;;
+ XEN_HYPER_GET_IVR
+ ;;
+ mov out0=r8 // pass cr.ivr as first arg
+#else
+ mov out0=cr.ivr // pass cr.ivr as first arg
+#endif
+ add out1=16,sp // pass pointer to pt_regs as second arg
+ ;;
+ srlz.d // make sure we see the effect of cr.ivr
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=ia64_handle_irq
+END(interrupt)
+
+ .org ia64_ivt+0x3400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3400 Entry 13 (size 64 bundles) Reserved
+ DBG_FAULT(13)
+ FAULT(13)
+
+ .org ia64_ivt+0x3800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3800 Entry 14 (size 64 bundles) Reserved
+ DBG_FAULT(14)
+ FAULT(14)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ *
+ * ia64_syscall_setup() is a separate subroutine so that it can
+ * allocate stacked registers so it can safely demine any
+ * potential NaT values from the input registers.
+ *
+ * On entry:
+ * - executing on bank 0 or bank 1 register set (doesn't matter)
+ * - r1: stack pointer
+ * - r2: current task pointer
+ * - r3: preserved
+ * - r11: original contents (saved ar.pfs to be saved)
+ * - r12: original contents (sp to be saved)
+ * - r13: original contents (tp to be saved)
+ * - r15: original contents (syscall # to be saved)
+ * - r18: saved bsp (after switching to kernel stack)
+ * - r19: saved b6
+ * - r20: saved r1 (gp)
+ * - r21: saved ar.fpsr
+ * - r22: kernel's register backing store base (krbs_base)
+ * - r23: saved ar.bspstore
+ * - r24: saved ar.rnat
+ * - r25: saved ar.unat
+ * - r26: saved ar.pfs
+ * - r27: saved ar.rsc
+ * - r28: saved cr.iip
+ * - r29: saved cr.ipsr
+ * - r31: saved pr
+ * - b0: original contents (to be saved)
+ * On exit:
+ * - p10: TRUE if syscall is invoked with more than 8 out
+ * registers or r15's Nat is true
+ * - r1: kernel's gp
+ * - r3: preserved (same as on entry)
+ * - r8: -EINVAL if p10 is true
+ * - r12: points to kernel stack
+ * - r13: points to current task
+ * - r14: preserved (same as on entry)
+ * - p13: preserved
+ * - p15: TRUE if interrupts need to be re-enabled
+ * - ar.fpsr: set to kernel settings
+ * - b6: preserved (same as on entry)
+ */
+#ifndef CONFIG_XEN
+GLOBAL_ENTRY(ia64_syscall_setup)
+#if PT(B6) != 0
+# error This code assumes that b6 is the first field in pt_regs.
+#endif
+ st8 [r1]=r19 // save b6
+ add r16=PT(CR_IPSR),r1 // initialize first base pointer
+ add r17=PT(R11),r1 // initialize second base pointer
+ ;;
+ alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable
+ st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr
+ tnat.nz p8,p0=in0
+
+ st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11
+ tnat.nz p9,p0=in1
+(pKStk) mov r18=r0 // make sure r18 isn't NaT
+ ;;
+
+ st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs
+ st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip
+ mov r28=b0 // save b0 (2 cyc)
+ ;;
+
+ st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat
+ dep r19=0,r19,38,26 // clear all bits but 0..37 [I0]
+(p8) mov in0=-1
+ ;;
+
+ st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs
+ extr.u r11=r19,7,7 // I0 // get sol of ar.pfs
+ and r8=0x7f,r19 // A // get sof of ar.pfs
+
+ st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc
+ tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0
+(p9) mov in1=-1
+ ;;
+
+(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8
+ tnat.nz p10,p0=in2
+ add r11=8,r11
+ ;;
+(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field
+(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field
+ tnat.nz p11,p0=in3
+ ;;
+(p10) mov in2=-1
+ tnat.nz p12,p0=in4 // [I0]
+(p11) mov in3=-1
+ ;;
+(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat
+(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore
+ shl r18=r18,16 // compute ar.rsc to be used for "loadrs"
+ ;;
+ st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates
+ st8 [r17]=r28,PT(R1)-PT(B0) // save b0
+ tnat.nz p13,p0=in5 // [I0]
+ ;;
+ st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs"
+ st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1
+(p12) mov in4=-1
+ ;;
+
+.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12
+.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13
+(p13) mov in5=-1
+ ;;
+ st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr
+ tnat.nz p13,p0=in6
+ cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8
+ ;;
+ mov r8=1
+(p9) tnat.nz p10,p0=r15
+ adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch)
+
+ st8.spill [r17]=r15 // save r15
+ tnat.nz p8,p0=in7
+ nop.i 0
+
+ mov r13=r2 // establish `current'
+ movl r1=__gp // establish kernel global pointer
+ ;;
+ st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error)
+(p13) mov in6=-1
+(p8) mov in7=-1
+
+ cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
+ movl r17=FPSR_DEFAULT
+ ;;
+ mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value
+(p10) mov r8=-EINVAL
+ br.ret.sptk.many b7
+END(ia64_syscall_setup)
+#endif
+
+ .org ia64_ivt+0x3c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x3c00 Entry 15 (size 64 bundles) Reserved
+ DBG_FAULT(15)
+ FAULT(15)
+
+ /*
+ * Squatting in this space ...
+ *
+ * This special case dispatcher for illegal operation faults allows preserved
+ * registers to be modified through a callback function (asm only) that is handed
+ * back from the fault handler in r8. Up to three arguments can be passed to the
+ * callback function by returning an aggregate with the callback as its first
+ * element, followed by the arguments.
+ */
+ENTRY(dispatch_illegal_op_fault)
+ .prologue
+ .body
+ SAVE_MIN_WITH_COVER
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ ;;
+ alloc r14=ar.pfs,0,0,1,0 // must be first in insn group
+ mov out0=ar.ec
+ ;;
+ SAVE_REST
+ PT_REGS_UNWIND_INFO(0)
+ ;;
+ br.call.sptk.many rp=ia64_illegal_op_fault
+.ret0: ;;
+ alloc r14=ar.pfs,0,0,3,0 // must be first in insn group
+ mov out0=r9
+ mov out1=r10
+ mov out2=r11
+ movl r15=ia64_leave_kernel
+ ;;
+ mov rp=r15
+ mov b6=r8
+ ;;
+ cmp.ne p6,p0=0,r8
+(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel
+ br.sptk.many ia64_leave_kernel
+END(dispatch_illegal_op_fault)
+
+ .org ia64_ivt+0x4000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4000 Entry 16 (size 64 bundles) Reserved
+ DBG_FAULT(16)
+ FAULT(16)
+
+ .org ia64_ivt+0x4400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4400 Entry 17 (size 64 bundles) Reserved
+ DBG_FAULT(17)
+ FAULT(17)
+
+ENTRY(non_syscall)
+ mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER
+ ;;
+ SAVE_MIN_WITH_COVER
+
+ // There is no particular reason for this code to be here, other than that
+ // there happens to be space here that would go unused otherwise. If this
+ // fault ever gets "unreserved", simply moved the following code to a more
+ // suitable spot...
+
+ alloc r14=ar.pfs,0,0,2,0
+ mov out0=cr.iim
+ add out1=16,sp
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ movl r15=ia64_leave_kernel
+ ;;
+ SAVE_REST
+ mov rp=r15
+ ;;
+ br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr
+END(non_syscall)
+
+ .org ia64_ivt+0x4800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4800 Entry 18 (size 64 bundles) Reserved
+ DBG_FAULT(18)
+ FAULT(18)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ENTRY(dispatch_unaligned_handler)
+ SAVE_MIN_WITH_COVER
+ ;;
+ alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
+ mov out0=cr.ifa
+ adds out1=16,sp
+
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ SAVE_REST
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.sptk.many ia64_prepare_handle_unaligned
+END(dispatch_unaligned_handler)
+
+ .org ia64_ivt+0x4c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x4c00 Entry 19 (size 64 bundles) Reserved
+ DBG_FAULT(19)
+ FAULT(19)
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ENTRY(dispatch_to_fault_handler)
+ /*
+ * Input:
+ * psr.ic: off
+ * r19: fault vector number (e.g., 24 for General Exception)
+ * r31: contains saved predicates (pr)
+ */
+ SAVE_MIN_WITH_COVER_R19
+ alloc r14=ar.pfs,0,0,5,0
+ mov out0=r15
+#ifdef CONFIG_XEN
+ movl out1=XSI_ISR
+ ;;
+ adds out2=XSI_IFA-XSI_ISR,out1
+ adds out3=XSI_IIM-XSI_ISR,out1
+ adds out4=XSI_ITIR-XSI_ISR,out1
+ ;;
+ ld8 out1=[out1]
+ ld8 out2=[out2]
+ ld8 out3=[out4]
+ ld8 out4=[out4]
+ ;;
+#else
+ mov out1=cr.isr
+ mov out2=cr.ifa
+ mov out3=cr.iim
+ mov out4=cr.itir
+ ;;
+#endif
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ ;;
+ SAVE_REST
+ movl r14=ia64_leave_kernel
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=ia64_fault
+END(dispatch_to_fault_handler)
+
+//
+// --- End of long entries, Beginning of short entries
+//
+
+ .org ia64_ivt+0x5000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
+ENTRY(page_not_present)
+ DBG_FAULT(20)
+ mov r16=cr.ifa
+ rsm psr.dt
+ /*
+ * The Linux page fault handler doesn't expect non-present pages to be in
+ * the TLB. Flush the existing entry now, so we meet that expectation.
+ */
+ mov r17=PAGE_SHIFT<<2
+ ;;
+ ptc.l r16,r17
+ ;;
+ mov r31=pr
+ srlz.d
+ br.sptk.many page_fault
+END(page_not_present)
+
+ .org ia64_ivt+0x5100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
+ENTRY(key_permission)
+ DBG_FAULT(21)
+ mov r16=cr.ifa
+ rsm psr.dt
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(key_permission)
+
+ .org ia64_ivt+0x5200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
+ENTRY(iaccess_rights)
+ DBG_FAULT(22)
+ mov r16=cr.ifa
+ rsm psr.dt
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(iaccess_rights)
+
+ .org ia64_ivt+0x5300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
+ENTRY(daccess_rights)
+ DBG_FAULT(23)
+#ifdef CONFIG_XEN
+ movl r16=XSI_IFA
+ ;;
+ ld8 r16=[r16]
+ ;;
+ XEN_HYPER_RSM_PSR_DT
+#else
+ mov r16=cr.ifa
+ rsm psr.dt
+#endif
+ mov r31=pr
+ ;;
+ srlz.d
+ br.sptk.many page_fault
+END(daccess_rights)
+
+ .org ia64_ivt+0x5400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
+ENTRY(general_exception)
+ DBG_FAULT(24)
+ mov r16=cr.isr
+ mov r31=pr
+ ;;
+ cmp4.eq p6,p0=0,r16
+(p6) br.sptk.many dispatch_illegal_op_fault
+ ;;
+ mov r19=24 // fault number
+ br.sptk.many dispatch_to_fault_handler
+END(general_exception)
+
+ .org ia64_ivt+0x5500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
+ENTRY(disabled_fp_reg)
+ DBG_FAULT(25)
+ rsm psr.dfh // ensure we can access fph
+ ;;
+ srlz.d
+ mov r31=pr
+ mov r19=25
+ br.sptk.many dispatch_to_fault_handler
+END(disabled_fp_reg)
+
+ .org ia64_ivt+0x5600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
+ENTRY(nat_consumption)
+ DBG_FAULT(26)
+
+ mov r16=cr.ipsr
+ mov r17=cr.isr
+ mov r31=pr // save PR
+ ;;
+ and r18=0xf,r17 // r18 = cr.ipsr.code{3:0}
+ tbit.z p6,p0=r17,IA64_ISR_NA_BIT
+ ;;
+ cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18
+ dep r16=-1,r16,IA64_PSR_ED_BIT,1
+(p6) br.cond.spnt 1f // branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH)
+ ;;
+ mov cr.ipsr=r16 // set cr.ipsr.na
+ mov pr=r31,-1
+ ;;
+ rfi
+
+1: mov pr=r31,-1
+ ;;
+ FAULT(26)
+END(nat_consumption)
+
+ .org ia64_ivt+0x5700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
+ENTRY(speculation_vector)
+ DBG_FAULT(27)
+ /*
+ * A [f]chk.[as] instruction needs to take the branch to the recovery code but
+ * this part of the architecture is not implemented in hardware on some CPUs, such
+ * as Itanium. Thus, in general we need to emulate the behavior. IIM contains
+ * the relative target (not yet sign extended). So after sign extending it we
+ * simply add it to IIP. We also need to reset the EI field of the IPSR to zero,
+ * i.e., the slot to restart into.
+ *
+ * cr.imm contains zero_ext(imm21)
+ */
+ mov r18=cr.iim
+ ;;
+ mov r17=cr.iip
+ shl r18=r18,43 // put sign bit in position (43=64-21)
+ ;;
+
+ mov r16=cr.ipsr
+ shr r18=r18,39 // sign extend (39=43-4)
+ ;;
+
+ add r17=r17,r18 // now add the offset
+ ;;
+ mov cr.iip=r17
+ dep r16=0,r16,41,2 // clear EI
+ ;;
+
+ mov cr.ipsr=r16
+ ;;
+
+#ifdef CONFIG_XEN
+ XEN_HYPER_RFI;
+#else
+ rfi // and go back
+#endif
+END(speculation_vector)
+
+ .org ia64_ivt+0x5800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5800 Entry 28 (size 16 bundles) Reserved
+ DBG_FAULT(28)
+ FAULT(28)
+
+ .org ia64_ivt+0x5900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
+ENTRY(debug_vector)
+ DBG_FAULT(29)
+ FAULT(29)
+END(debug_vector)
+
+ .org ia64_ivt+0x5a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
+ENTRY(unaligned_access)
+ DBG_FAULT(30)
+ mov r31=pr // prepare to save predicates
+ ;;
+ br.sptk.many dispatch_unaligned_handler
+END(unaligned_access)
+
+ .org ia64_ivt+0x5b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
+ENTRY(unsupported_data_reference)
+ DBG_FAULT(31)
+ FAULT(31)
+END(unsupported_data_reference)
+
+ .org ia64_ivt+0x5c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
+ENTRY(floating_point_fault)
+ DBG_FAULT(32)
+ FAULT(32)
+END(floating_point_fault)
+
+ .org ia64_ivt+0x5d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
+ENTRY(floating_point_trap)
+ DBG_FAULT(33)
+ FAULT(33)
+END(floating_point_trap)
+
+ .org ia64_ivt+0x5e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
+ENTRY(lower_privilege_trap)
+ DBG_FAULT(34)
+ FAULT(34)
+END(lower_privilege_trap)
+
+ .org ia64_ivt+0x5f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
+ENTRY(taken_branch_trap)
+ DBG_FAULT(35)
+ FAULT(35)
+END(taken_branch_trap)
+
+ .org ia64_ivt+0x6000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
+ENTRY(single_step_trap)
+ DBG_FAULT(36)
+ FAULT(36)
+END(single_step_trap)
+
+ .org ia64_ivt+0x6100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6100 Entry 37 (size 16 bundles) Reserved
+ DBG_FAULT(37)
+ FAULT(37)
+
+ .org ia64_ivt+0x6200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6200 Entry 38 (size 16 bundles) Reserved
+ DBG_FAULT(38)
+ FAULT(38)
+
+ .org ia64_ivt+0x6300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6300 Entry 39 (size 16 bundles) Reserved
+ DBG_FAULT(39)
+ FAULT(39)
+
+ .org ia64_ivt+0x6400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6400 Entry 40 (size 16 bundles) Reserved
+ DBG_FAULT(40)
+ FAULT(40)
+
+ .org ia64_ivt+0x6500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6500 Entry 41 (size 16 bundles) Reserved
+ DBG_FAULT(41)
+ FAULT(41)
+
+ .org ia64_ivt+0x6600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6600 Entry 42 (size 16 bundles) Reserved
+ DBG_FAULT(42)
+ FAULT(42)
+
+ .org ia64_ivt+0x6700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6700 Entry 43 (size 16 bundles) Reserved
+ DBG_FAULT(43)
+ FAULT(43)
+
+ .org ia64_ivt+0x6800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6800 Entry 44 (size 16 bundles) Reserved
+ DBG_FAULT(44)
+ FAULT(44)
+
+ .org ia64_ivt+0x6900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
+ENTRY(ia32_exception)
+ DBG_FAULT(45)
+ FAULT(45)
+END(ia32_exception)
+
+ .org ia64_ivt+0x6a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
+ENTRY(ia32_intercept)
+ DBG_FAULT(46)
+#ifdef CONFIG_IA32_SUPPORT
+ mov r31=pr
+ mov r16=cr.isr
+ ;;
+ extr.u r17=r16,16,8 // get ISR.code
+ mov r18=ar.eflag
+ mov r19=cr.iim // old eflag value
+ ;;
+ cmp.ne p6,p0=2,r17
+(p6) br.cond.spnt 1f // not a system flag fault
+ xor r16=r18,r19
+ ;;
+ extr.u r17=r16,18,1 // get the eflags.ac bit
+ ;;
+ cmp.eq p6,p0=0,r17
+(p6) br.cond.spnt 1f // eflags.ac bit didn't change
+ ;;
+ mov pr=r31,-1 // restore predicate registers
+#ifdef CONFIG_XEN
+ XEN_HYPER_RFI;
+#else
+ rfi
+#endif
+
+1:
+#endif // CONFIG_IA32_SUPPORT
+ FAULT(46)
+END(ia32_intercept)
+
+ .org ia64_ivt+0x6b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
+ENTRY(ia32_interrupt)
+ DBG_FAULT(47)
+#ifdef CONFIG_IA32_SUPPORT
+ mov r31=pr
+ br.sptk.many dispatch_to_ia32_handler
+#else
+ FAULT(47)
+#endif
+END(ia32_interrupt)
+
+ .org ia64_ivt+0x6c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6c00 Entry 48 (size 16 bundles) Reserved
+ DBG_FAULT(48)
+ FAULT(48)
+
+ .org ia64_ivt+0x6d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6d00 Entry 49 (size 16 bundles) Reserved
+ DBG_FAULT(49)
+ FAULT(49)
+
+ .org ia64_ivt+0x6e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6e00 Entry 50 (size 16 bundles) Reserved
+ DBG_FAULT(50)
+ FAULT(50)
+
+ .org ia64_ivt+0x6f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x6f00 Entry 51 (size 16 bundles) Reserved
+ DBG_FAULT(51)
+ FAULT(51)
+
+ .org ia64_ivt+0x7000
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7000 Entry 52 (size 16 bundles) Reserved
+ DBG_FAULT(52)
+ FAULT(52)
+
+ .org ia64_ivt+0x7100
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7100 Entry 53 (size 16 bundles) Reserved
+ DBG_FAULT(53)
+ FAULT(53)
+
+ .org ia64_ivt+0x7200
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7200 Entry 54 (size 16 bundles) Reserved
+ DBG_FAULT(54)
+ FAULT(54)
+
+ .org ia64_ivt+0x7300
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7300 Entry 55 (size 16 bundles) Reserved
+ DBG_FAULT(55)
+ FAULT(55)
+
+ .org ia64_ivt+0x7400
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7400 Entry 56 (size 16 bundles) Reserved
+ DBG_FAULT(56)
+ FAULT(56)
+
+ .org ia64_ivt+0x7500
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7500 Entry 57 (size 16 bundles) Reserved
+ DBG_FAULT(57)
+ FAULT(57)
+
+ .org ia64_ivt+0x7600
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7600 Entry 58 (size 16 bundles) Reserved
+ DBG_FAULT(58)
+ FAULT(58)
+
+ .org ia64_ivt+0x7700
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7700 Entry 59 (size 16 bundles) Reserved
+ DBG_FAULT(59)
+ FAULT(59)
+
+ .org ia64_ivt+0x7800
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7800 Entry 60 (size 16 bundles) Reserved
+ DBG_FAULT(60)
+ FAULT(60)
+
+ .org ia64_ivt+0x7900
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7900 Entry 61 (size 16 bundles) Reserved
+ DBG_FAULT(61)
+ FAULT(61)
+
+ .org ia64_ivt+0x7a00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7a00 Entry 62 (size 16 bundles) Reserved
+ DBG_FAULT(62)
+ FAULT(62)
+
+ .org ia64_ivt+0x7b00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7b00 Entry 63 (size 16 bundles) Reserved
+ DBG_FAULT(63)
+ FAULT(63)
+
+ .org ia64_ivt+0x7c00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7c00 Entry 64 (size 16 bundles) Reserved
+ DBG_FAULT(64)
+ FAULT(64)
+
+ .org ia64_ivt+0x7d00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7d00 Entry 65 (size 16 bundles) Reserved
+ DBG_FAULT(65)
+ FAULT(65)
+
+ .org ia64_ivt+0x7e00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7e00 Entry 66 (size 16 bundles) Reserved
+ DBG_FAULT(66)
+ FAULT(66)
+
+ .org ia64_ivt+0x7f00
+/////////////////////////////////////////////////////////////////////////////////////////
+// 0x7f00 Entry 67 (size 16 bundles) Reserved
+ DBG_FAULT(67)
+ FAULT(67)
+
+#ifdef CONFIG_IA32_SUPPORT
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+ // IA32 interrupt entry point
+
+ENTRY(dispatch_to_ia32_handler)
+ SAVE_MIN
+ ;;
+ mov r14=cr.isr
+ ssm psr.ic | PSR_DEFAULT_BITS
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+(p15) ssm psr.i
+ adds r3=8,r2 // Base pointer for SAVE_REST
+ ;;
+ SAVE_REST
+ ;;
+ mov r15=0x80
+ shr r14=r14,16 // Get interrupt number
+ ;;
+ cmp.ne p6,p0=r14,r15
+(p6) br.call.dpnt.many b6=non_ia32_syscall
+
+ adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions
+ adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
+ ;;
+ cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
+ ld8 r8=[r14] // get r8
+ ;;
+ st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
+ ;;
+ alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
+ ;;
+ ld4 r8=[r14],8 // r8 == eax (syscall number)
+ mov r15=IA32_NR_syscalls
+ ;;
+ cmp.ltu.unc p6,p7=r8,r15
+ ld4 out1=[r14],8 // r9 == ecx
+ ;;
+ ld4 out2=[r14],8 // r10 == edx
+ ;;
+ ld4 out0=[r14] // r11 == ebx
+ adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
+ ;;
+ ld4 out5=[r14],PT(R14)-PT(R13) // r13 == ebp
+ ;;
+ ld4 out3=[r14],PT(R15)-PT(R14) // r14 == esi
+ adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
+ ;;
+ ld4 out4=[r14] // r15 == edi
+ movl r16=ia32_syscall_table
+ ;;
+(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number
+ ld4 r2=[r2] // r2 = current_thread_info()->flags
+ ;;
+ ld8 r16=[r16]
+ and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit
+ ;;
+ mov b6=r16
+ movl r15=ia32_ret_from_syscall
+ cmp.eq p8,p0=r2,r0
+ ;;
+ mov rp=r15
+(p8) br.call.sptk.many b6=b6
+ br.cond.sptk ia32_trace_syscall
+
+non_ia32_syscall:
+ alloc r15=ar.pfs,0,0,2,0
+ mov out0=r14 // interrupt #
+ add out1=16,sp // pointer to pt_regs
+ ;; // avoid WAW on CFM
+ br.call.sptk.many rp=ia32_bad_interrupt
+.ret1: movl r15=ia64_leave_kernel
+ ;;
+ mov rp=r15
+ br.ret.sptk.many rp
+END(dispatch_to_ia32_handler)
+#endif /* CONFIG_IA32_SUPPORT */
+
+#ifdef CONFIG_XEN
+ .section .text,"ax"
+GLOBAL_ENTRY(xen_event_callback)
+ mov r31=pr // prepare to save predicates
+ ;;
+ SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3
+ ;;
+ movl r3=XSI_PSR_IC
+ mov r14=1
+ ;;
+ st4 [r3]=r14
+ ;;
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ srlz.i // ensure everybody knows psr.ic is back on
+ ;;
+ SAVE_REST
+ ;;
+1:
+ alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
+ add out0=16,sp // pass pointer to pt_regs as first arg
+ ;;
+ br.call.sptk.many b0=xen_evtchn_do_upcall
+ ;;
+ movl r20=XSI_PSR_I_ADDR
+ ;;
+ ld8 r20=[r20]
+ ;;
+ adds r20=-1,r20 // vcpu_info->evtchn_upcall_pending
+ ;;
+ ld1 r20=[r20]
+ ;;
+ cmp.ne p6,p0=r20,r0 // if there are pending events,
+ (p6) br.spnt.few 1b // call evtchn_do_upcall again.
+ br.sptk.many ia64_leave_kernel
+END(xen_event_callback)
+
+
+ /*
+ * There is no particular reason for this code to be here, other than that
+ * there happens to be space here that would go unused otherwise. If this
+ * fault ever gets "unreserved", simply moved the following code to a more
+ * suitable spot...
+ */
+
+GLOBAL_ENTRY(xen_bsw1)
+ /* FIXME: THIS CODE IS NOT NaT SAFE! */
+ mov r14=ar.unat
+ movl r30=XSI_B1NAT
+ ;;
+ ld8 r30=[r30];;
+ mov ar.unat=r30
+ movl r30=XSI_BANKNUM;
+ mov r31=1;;
+ st4 [r30]=r31;
+ movl r30=XSI_BANK1_R16;
+ movl r31=XSI_BANK1_R16+8;;
+ ld8.fill r16=[r30],16; ld8.fill r17=[r31],16;;
+ ld8.fill r18=[r30],16; ld8.fill r19=[r31],16;;
+ ld8.fill r20=[r30],16; ld8.fill r21=[r31],16;;
+ ld8.fill r22=[r30],16; ld8.fill r23=[r31],16;;
+ ld8.fill r24=[r30],16; ld8.fill r25=[r31],16;;
+ ld8.fill r26=[r30],16; ld8.fill r27=[r31],16;;
+ ld8.fill r28=[r30],16; ld8.fill r29=[r31],16;;
+ ld8.fill r30=[r30]; ld8.fill r31=[r31];;
+ mov ar.unat=r14
+ br.ret.sptk.many b0
+END(xen_bsw1)
+
+#endif
diff --git a/arch/ia64/xen/xenminstate.h b/arch/ia64/xen/xenminstate.h
new file mode 100644
index 0000000..eb199db
--- /dev/null
+++ b/arch/ia64/xen/xenminstate.h
@@ -0,0 +1,320 @@
+#include <asm/cache.h>
+
+#ifdef CONFIG_XEN
+#include "../kernel/entry.h"
+#else
+#include "entry.h"
+#endif
+
+/*
+ * 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
+ * CONFIG_XEN note: p6/p7 are not 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.
+ */
+#ifdef CONFIG_XEN
+#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \
+ mov r16=IA64_KR(CURRENT); /* M */ \
+ mov r27=ar.rsc; /* M */ \
+ mov r20=r1; /* A */ \
+ mov r25=ar.unat; /* M */ \
+ /* mov r29=cr.ipsr; /* M */ \
+ movl r29=XSI_IPSR;; \
+ ld8 r29=[r29];; \
+ mov r26=ar.pfs; /* I */ \
+ /* mov r28=cr.iip; /* M */ \
+ movl r28=XSI_IIP;; \
+ ld8 r28=[r28];; \
+ mov r21=ar.fpsr; /* M */ \
+ COVER; /* B;; (or nothing) */ \
+ ;; \
+ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \
+ ;; \
+ ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \
+ st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \
+ adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \
+ /* switch from user to kernel RBS: */ \
+ ;; \
+ invala; /* M */ \
+ /* SAVE_IFS; /* see xen special handling below */ \
+ cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \
+ ;; \
+(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
+ ;; \
+(pUStk) mov.m r24=ar.rnat; \
+(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \
+(pKStk) mov r1=sp; /* get sp */ \
+ ;; \
+(pUStk) lfetch.fault.excl.nt1 [r22]; \
+(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
+(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
+ ;; \
+(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
+(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
+ ;; \
+(pUStk) mov r18=ar.bsp; \
+(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
+ adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest 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 */ \
+(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \
+ ;; \
+.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; \
+ ;; \
+ /* xen special handling for possibly lazy cover */ \
+ movl r8=XSI_PRECOVER_IFS; \
+ ;; \
+ ld8 r30=[r8]; \
+ ;; \
+ st8 [r16]=r28,16; /* save cr.iip */ \
+ st8 [r17]=r30,16; /* save cr.ifs */ \
+(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \
+ mov r8=ar.ccv; \
+ mov r9=ar.csd; \
+ mov r10=ar.ssd; \
+ movl r11=FPSR_DEFAULT; /* L-unit */ \
+ ;; \
+ st8 [r16]=r25,16; /* save ar.unat */ \
+ st8 [r17]=r26,16; /* save ar.pfs */ \
+ shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \
+ ;; \
+ st8 [r16]=r27,16; /* save ar.rsc */ \
+(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \
+(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \
+ ;; /* avoid RAW on r16 & r17 */ \
+(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \
+ st8 [r17]=r31,16; /* save predicates */ \
+(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \
+ ;; \
+ st8 [r16]=r29,16; /* save b0 */ \
+ st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \
+ cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \
+ ;; \
+.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]=r21,16; /* save ar.fpsr */ \
+ mov r13=IA64_KR(CURRENT); /* 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; \
+ ;; \
+ EXTRA; \
+ mov r2=b0; br.call.sptk b0=xen_bsw1;; mov b0=r2; \
+ adds r2=IA64_PT_REGS_R16_OFFSET,r1; \
+ ;; \
+ movl r1=__gp; /* establish kernel global pointer */ \
+ ;; \
+ /*bsw.1;*/ /* switch back to bank 1 (must be last in insn group) */ \
+ ;;
+#else
+#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \
+ mov r16=IA64_KR(CURRENT); /* M */ \
+ 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 r28=cr.iip; /* M */ \
+ mov r21=ar.fpsr; /* M */ \
+ COVER; /* B;; (or nothing) */ \
+ ;; \
+ adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \
+ ;; \
+ ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \
+ st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \
+ adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \
+ /* switch from user to kernel RBS: */ \
+ ;; \
+ invala; /* M */ \
+ SAVE_IFS; \
+ cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \
+ ;; \
+(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
+ ;; \
+(pUStk) mov.m r24=ar.rnat; \
+(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \
+(pKStk) mov r1=sp; /* get sp */ \
+ ;; \
+(pUStk) lfetch.fault.excl.nt1 [r22]; \
+(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
+(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
+ ;; \
+(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
+(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
+ ;; \
+(pUStk) mov r18=ar.bsp; \
+(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
+ adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest 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 */ \
+(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \
+ ;; \
+.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; \
+ ;; \
+ st8 [r16]=r28,16; /* save cr.iip */ \
+ st8 [r17]=r30,16; /* save cr.ifs */ \
+(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \
+ mov r8=ar.ccv; \
+ mov r9=ar.csd; \
+ mov r10=ar.ssd; \
+ movl r11=FPSR_DEFAULT; /* L-unit */ \
+ ;; \
+ st8 [r16]=r25,16; /* save ar.unat */ \
+ st8 [r17]=r26,16; /* save ar.pfs */ \
+ shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \
+ ;; \
+ st8 [r16]=r27,16; /* save ar.rsc */ \
+(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \
+(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \
+ ;; /* avoid RAW on r16 & r17 */ \
+(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \
+ st8 [r17]=r31,16; /* save predicates */ \
+(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \
+ ;; \
+ st8 [r16]=r29,16; /* save b0 */ \
+ st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \
+ cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \
+ ;; \
+.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]=r21,16; /* save ar.fpsr */ \
+ mov r13=IA64_KR(CURRENT); /* 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=IA64_PT_REGS_R16_OFFSET,r1; \
+ ;; \
+ EXTRA; \
+ movl r1=__gp; /* establish kernel global pointer */ \
+ ;; \
+ bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
+ ;;
+#endif
+
+/*
+ * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
+ *
+ * Assumed state upon entry:
+ * psr.ic: on
+ * r2: points to &pt_regs.r16
+ * r3: points to &pt_regs.r17
+ * 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 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; /* M-unit */ \
+ st8 [r2]=r8,8; /* ar.ccv */ \
+ adds r24=PT(B6)-PT(F7),r3; \
+ ;; \
+ stf.spill [r2]=f6,32; \
+ stf.spill [r3]=f7,32; \
+ ;; \
+ stf.spill [r2]=f8,32; \
+ stf.spill [r3]=f9,32; \
+ ;; \
+ stf.spill [r2]=f10; \
+ stf.spill [r3]=f11; \
+ adds r25=PT(B7)-PT(F11),r3; \
+ ;; \
+ st8 [r24]=r18,16; /* b6 */ \
+ st8 [r25]=r19,16; /* b7 */ \
+ ;; \
+ st8 [r24]=r9; /* ar.csd */ \
+ st8 [r25]=r10; /* ar.ssd */ \
+ ;;
+
+#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs,)
+#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19)
+#ifdef CONFIG_XEN
+#define SAVE_MIN break 0;; /* FIXME: non-cover version only for ia32 support? */
+#else
+#define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, )
+#endif
diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h
new file mode 100644
index 0000000..b8dce79
--- /dev/null
+++ b/include/asm-ia64/privop.h
@@ -0,0 +1,26 @@
+#ifndef _ASM_IA64_PRIVOP_H
+#define _ASM_IA64_PRIVOP_H
+
+#ifndef _ASM_IA64_INTRINSICS_H
+#error "don't include privop.h directly. instead include intrinsics.h"
+#endif
+/*
+ * Copyright (C) 2005 Hewlett-Packard Co
+ * Dan Magenheimer <dan.magenheimer@hp.com>
+ *
+ */
+
+#ifdef CONFIG_XEN
+#include <asm/xen/privop.h>
+#endif
+
+/* fallback for native case */
+
+#ifndef IA64_PARAVIRTUALIZED_ENTRY
+#define ia64_switch_to __ia64_switch_to
+#define ia64_leave_syscall __ia64_leave_syscall
+#define ia64_work_processed_syscall __ia64_work_processed_syscall
+#define ia64_leave_kernel __ia64_leave_kernel
+#endif /* !IA64_PARAVIRTUALIZED_ENTRY */
+
+#endif /* _ASM_IA64_PRIVOP_H */
diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h
index dd3e5ec..c8a5a0d 100644
--- a/include/asm-ia64/xen/privop.h
+++ b/include/asm-ia64/xen/privop.h
@@ -70,4 +70,26 @@
#define XSI_IHA (XSI_BASE + XSI_IHA_OFS)
#endif
+/* these routines utilize privilege-sensitive or performance-sensitive
+ * privileged instructions so the code must be replaced with
+ * paravirtualized versions */
+#ifndef CONFIG_PARAVIRT_ENTRY
+#define IA64_PARAVIRTUALIZED_ENTRY
+#define ia64_switch_to xen_switch_to
+#define ia64_leave_syscall xen_leave_syscall
+#define ia64_work_processed_syscall xen_work_processed_syscall_with_check
+#define ia64_leave_kernel xen_leave_kernel
+#endif /* !CONFIG_PARAVIRT_ENTRY */
+
+#ifdef CONFIG_XEN
+#ifdef __ASSEMBLY__
+#define BR_IF_NATIVE(target, reg, pred) \
+ .body ; \
+ movl reg=running_on_xen;; ; \
+ ld4 reg=[reg];; ; \
+ cmp.eq pred,p0=reg,r0 ; \
+ (pred) br.cond.sptk.many target;;
+#endif /* __ASSEMBLY__ */
+#endif
+
#endif /* _ASM_IA64_XEN_PRIVOP_H */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 09/28] ia64/xen: paravirtualize pal_call_static().
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (7 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 08/28] RFC: ia64/xen: xen hand written assembly code paravirtualization yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 10/28] RFC: ia64/xen: introduce xen paravirtualized intrinsic operations for privileged instruction yamahata
` (23 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0009-ia64-xen-paravirtualize-pal_call_static.patch --]
[-- Type: text/plain, Size: 3883 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/pal.S | 5 ++-
arch/ia64/xen/xenpal.S | 76 +++++++++++++++++++++++++++++++++++++++++
include/asm-ia64/privop.h | 1 +
include/asm-ia64/xen/privop.h | 1 +
4 files changed, 81 insertions(+), 2 deletions(-)
create mode 100644 arch/ia64/xen/xenpal.S
diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S
index 0b53344..de7252d 100644
--- a/arch/ia64/kernel/pal.S
+++ b/arch/ia64/kernel/pal.S
@@ -16,6 +16,7 @@
#include <asm/processor.h>
.data
+ .globl pal_entry_point
pal_entry_point:
data8 ia64_pal_default_handler
.text
@@ -52,7 +53,7 @@ END(ia64_pal_default_handler)
* in0 Index of PAL service
* in1 - in3 Remaining PAL arguments
*/
-GLOBAL_ENTRY(ia64_pal_call_static)
+GLOBAL_ENTRY(__ia64_pal_call_static)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
alloc loc1 = ar.pfs,4,5,0,0
movl loc2 = pal_entry_point
@@ -86,7 +87,7 @@ GLOBAL_ENTRY(ia64_pal_call_static)
;;
srlz.d // seralize restoration of psr.l
br.ret.sptk.many b0
-END(ia64_pal_call_static)
+END(__ia64_pal_call_static)
/*
* Make a PAL call using the stacked registers calling convention.
diff --git a/arch/ia64/xen/xenpal.S b/arch/ia64/xen/xenpal.S
new file mode 100644
index 0000000..cf8dff9
--- /dev/null
+++ b/arch/ia64/xen/xenpal.S
@@ -0,0 +1,76 @@
+/*
+ * ia64/xen/xenpal.S
+ *
+ * Alternate PAL routines for Xen. Heavily leveraged from
+ * ia64/kernel/pal.S
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ * Dan Magenheimer <dan.magenheimer@.hp.com>
+ */
+
+#include <asm/asmmacro.h>
+#include <asm/processor.h>
+#include <asm/paravirt_nop.h>
+
+GLOBAL_ENTRY(xen_pal_call_static)
+#ifdef CONFIG_XEN
+ BR_IF_NATIVE(__ia64_pal_call_static, r22, p7)
+#endif
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
+ alloc loc1 = ar.pfs,4,5,0,0
+ movl loc2 = pal_entry_point
+1: {
+ mov r28 = in0
+ mov r29 = in1
+ mov r8 = ip
+ }
+ ;;
+ ld8 loc2 = [loc2] // loc2 <- entry point
+ adds r8 = 1f-1b,r8
+ mov loc4=ar.rsc // save RSE configuration
+ ;;
+ mov ar.rsc=0 // put RSE in enforced lazy, LE mode
+#ifdef CONFIG_XEN
+ mov r9 = r8
+ XEN_HYPER_GET_PSR
+ ;;
+ mov loc3 = r8
+ mov r8 = r9
+ ;;
+#else
+ mov loc3 = psr
+#endif
+ mov loc0 = rp
+ .body
+ mov r30 = in2
+
+#ifdef CONFIG_XEN
+ // this is low priority for paravirtualization, but is called
+ // from the idle loop so confuses privop counting
+ movl r31=XSI_PSR_I_ADDR
+ ;;
+ ld8 r31=[r31]
+ mov r22=1
+ ;;
+ st1 [r31]=r22
+ ;;
+ mov r31 = in3
+ mov b7 = loc2
+ ;;
+#else
+ mov r31 = in3
+ mov b7 = loc2
+
+(p7) rsm psr.i
+ ;;
+#endif
+ mov rp = r8
+ br.cond.sptk.many b7
+1: mov psr.l = loc3
+ mov ar.rsc = loc4 // restore RSE configuration
+ mov ar.pfs = loc1
+ mov rp = loc0
+ ;;
+ srlz.d // seralize restoration of psr.l
+ br.ret.sptk.many b0
+END(xen_pal_call_static)
diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h
index b8dce79..09c14ae 100644
--- a/include/asm-ia64/privop.h
+++ b/include/asm-ia64/privop.h
@@ -21,6 +21,7 @@
#define ia64_leave_syscall __ia64_leave_syscall
#define ia64_work_processed_syscall __ia64_work_processed_syscall
#define ia64_leave_kernel __ia64_leave_kernel
+#define ia64_pal_call_static __ia64_pal_call_static
#endif /* !IA64_PARAVIRTUALIZED_ENTRY */
#endif /* _ASM_IA64_PRIVOP_H */
diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h
index c8a5a0d..0fa8aa6 100644
--- a/include/asm-ia64/xen/privop.h
+++ b/include/asm-ia64/xen/privop.h
@@ -79,6 +79,7 @@
#define ia64_leave_syscall xen_leave_syscall
#define ia64_work_processed_syscall xen_work_processed_syscall_with_check
#define ia64_leave_kernel xen_leave_kernel
+#define ia64_pal_call_static xen_pal_call_static
#endif /* !CONFIG_PARAVIRT_ENTRY */
#ifdef CONFIG_XEN
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 10/28] RFC: ia64/xen: introduce xen paravirtualized intrinsic operations for privileged instruction.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (8 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 09/28] ia64/xen: paravirtualize pal_call_static() yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 11/28] ia64: introduce basic facilities for binary patching yamahata
` (22 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0010-ia64-xen-introduce-xen-paravirtualized-intrinsic-op.patch --]
[-- Type: text/plain, Size: 31023 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/xen/hypercall.S | 124 ++++++++++
include/asm-ia64/gcc_intrin.h | 58 +++---
include/asm-ia64/intel_intrin.h | 64 +++---
include/asm-ia64/intrinsics.h | 14 +-
include/asm-ia64/privop.h | 36 +++
include/asm-ia64/xen/privop.h | 489 +++++++++++++++++++++++++++++++++++++++
6 files changed, 717 insertions(+), 68 deletions(-)
create mode 100644 arch/ia64/xen/hypercall.S
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
new file mode 100644
index 0000000..a96f278
--- /dev/null
+++ b/arch/ia64/xen/hypercall.S
@@ -0,0 +1,124 @@
+/*
+ * Support routines for Xen hypercalls
+ *
+ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
+ */
+
+#include <asm/asmmacro.h>
+#include <asm/intrinsics.h>
+
+#ifdef __INTEL_COMPILER
+# undef ASM_SUPPORTED
+#else
+# define ASM_SUPPORTED
+#endif
+
+#ifndef ASM_SUPPORTED
+GLOBAL_ENTRY(xen_get_psr)
+ XEN_HYPER_GET_PSR
+ br.ret.sptk.many rp
+ ;;
+END(xen_get_psr)
+
+GLOBAL_ENTRY(xen_get_ivr)
+ XEN_HYPER_GET_IVR
+ br.ret.sptk.many rp
+ ;;
+END(xen_get_ivr)
+
+GLOBAL_ENTRY(xen_get_tpr)
+ XEN_HYPER_GET_TPR
+ br.ret.sptk.many rp
+ ;;
+END(xen_get_tpr)
+
+GLOBAL_ENTRY(xen_set_tpr)
+ mov r8=r32
+ XEN_HYPER_SET_TPR
+ br.ret.sptk.many rp
+ ;;
+END(xen_set_tpr)
+
+GLOBAL_ENTRY(xen_eoi)
+ mov r8=r32
+ XEN_HYPER_EOI
+ br.ret.sptk.many rp
+ ;;
+END(xen_eoi)
+
+GLOBAL_ENTRY(xen_thash)
+ mov r8=r32
+ XEN_HYPER_THASH
+ br.ret.sptk.many rp
+ ;;
+END(xen_thash)
+
+GLOBAL_ENTRY(xen_set_itm)
+ mov r8=r32
+ XEN_HYPER_SET_ITM
+ br.ret.sptk.many rp
+ ;;
+END(xen_set_itm)
+
+GLOBAL_ENTRY(xen_ptcga)
+ mov r8=r32
+ mov r9=r33
+ XEN_HYPER_PTC_GA
+ br.ret.sptk.many rp
+ ;;
+END(xen_ptcga)
+
+GLOBAL_ENTRY(xen_get_rr)
+ mov r8=r32
+ XEN_HYPER_GET_RR
+ br.ret.sptk.many rp
+ ;;
+END(xen_get_rr)
+
+GLOBAL_ENTRY(xen_set_rr)
+ mov r8=r32
+ mov r9=r33
+ XEN_HYPER_SET_RR
+ br.ret.sptk.many rp
+ ;;
+END(xen_set_rr)
+
+GLOBAL_ENTRY(xen_set_kr)
+ mov r8=r32
+ mov r9=r33
+ XEN_HYPER_SET_KR
+ br.ret.sptk.many rp
+END(xen_set_kr)
+
+GLOBAL_ENTRY(xen_fc)
+ mov r8=r32
+ XEN_HYPER_FC
+ br.ret.sptk.many rp
+END(xen_fc)
+
+GLOBAL_ENTRY(xen_get_cpuid)
+ mov r8=r32
+ XEN_HYPER_GET_CPUID
+ br.ret.sptk.many rp
+END(xen_get_cpuid)
+
+GLOBAL_ENTRY(xen_get_pmd)
+ mov r8=r32
+ XEN_HYPER_GET_PMD
+ br.ret.sptk.many rp
+END(xen_get_pmd)
+
+#ifdef CONFIG_IA32_SUPPORT
+GLOBAL_ENTRY(xen_get_eflag)
+ XEN_HYPER_GET_EFLAG
+ br.ret.sptk.many rp
+END(xen_get_eflag)
+
+// some bits aren't set if pl!=0, see SDM vol1 3.1.8
+GLOBAL_ENTRY(xen_set_eflag)
+ mov r8=r32
+ XEN_HYPER_SET_EFLAG
+ br.ret.sptk.many rp
+END(xen_set_eflag)
+#endif /* CONFIG_IA32_SUPPORT */
+#endif /* ASM_SUPPORTED */
diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
index de2ed2c..5fe2932 100644
--- a/include/asm-ia64/gcc_intrin.h
+++ b/include/asm-ia64/gcc_intrin.h
@@ -28,7 +28,7 @@ extern void ia64_bad_param_for_getreg (void);
register unsigned long ia64_r13 asm ("r13") __used;
#endif
-#define ia64_setreg(regnum, val) \
+#define __ia64_setreg(regnum, val) \
({ \
switch (regnum) { \
case _IA64_REG_PSR_L: \
@@ -57,7 +57,7 @@ register unsigned long ia64_r13 asm ("r13") __used;
} \
})
-#define ia64_getreg(regnum) \
+#define __ia64_getreg(regnum) \
({ \
__u64 ia64_intri_res; \
\
@@ -94,7 +94,7 @@ register unsigned long ia64_r13 asm ("r13") __used;
#define ia64_hint_pause 0
-#define ia64_hint(mode) \
+#define __ia64_hint(mode) \
({ \
switch (mode) { \
case ia64_hint_pause: \
@@ -381,7 +381,7 @@ register unsigned long ia64_r13 asm ("r13") __used;
#define ia64_invala() asm volatile ("invala" ::: "memory")
-#define ia64_thash(addr) \
+#define __ia64_thash(addr) \
({ \
__u64 ia64_intri_res; \
asm volatile ("thash %0=%1" : "=r"(ia64_intri_res) : "r" (addr)); \
@@ -401,18 +401,18 @@ register unsigned long ia64_r13 asm ("r13") __used;
#define ia64_nop(x) asm volatile ("nop %0"::"i"(x));
-#define ia64_itci(addr) asm volatile ("itc.i %0;;" :: "r"(addr) : "memory")
+#define __ia64_itci(addr) asm volatile ("itc.i %0;;" :: "r"(addr) : "memory")
-#define ia64_itcd(addr) asm volatile ("itc.d %0;;" :: "r"(addr) : "memory")
+#define __ia64_itcd(addr) asm volatile ("itc.d %0;;" :: "r"(addr) : "memory")
-#define ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1" \
+#define __ia64_itri(trnum, addr) asm volatile ("itr.i itr[%0]=%1" \
:: "r"(trnum), "r"(addr) : "memory")
-#define ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1" \
+#define __ia64_itrd(trnum, addr) asm volatile ("itr.d dtr[%0]=%1" \
:: "r"(trnum), "r"(addr) : "memory")
-#define ia64_tpa(addr) \
+#define __ia64_tpa(addr) \
({ \
__u64 ia64_pa; \
asm volatile ("tpa %0 = %1" : "=r"(ia64_pa) : "r"(addr) : "memory"); \
@@ -422,22 +422,22 @@ register unsigned long ia64_r13 asm ("r13") __used;
#define __ia64_set_dbr(index, val) \
asm volatile ("mov dbr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-#define ia64_set_ibr(index, val) \
+#define __ia64_set_ibr(index, val) \
asm volatile ("mov ibr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-#define ia64_set_pkr(index, val) \
+#define __ia64_set_pkr(index, val) \
asm volatile ("mov pkr[%0]=%1" :: "r"(index), "r"(val) : "memory")
-#define ia64_set_pmc(index, val) \
+#define __ia64_set_pmc(index, val) \
asm volatile ("mov pmc[%0]=%1" :: "r"(index), "r"(val) : "memory")
-#define ia64_set_pmd(index, val) \
+#define __ia64_set_pmd(index, val) \
asm volatile ("mov pmd[%0]=%1" :: "r"(index), "r"(val) : "memory")
-#define ia64_set_rr(index, val) \
+#define __ia64_set_rr(index, val) \
asm volatile ("mov rr[%0]=%1" :: "r"(index), "r"(val) : "memory");
-#define ia64_get_cpuid(index) \
+#define __ia64_get_cpuid(index) \
({ \
__u64 ia64_intri_res; \
asm volatile ("mov %0=cpuid[%r1]" : "=r"(ia64_intri_res) : "rO"(index)); \
@@ -451,21 +451,21 @@ register unsigned long ia64_r13 asm ("r13") __used;
ia64_intri_res; \
})
-#define ia64_get_ibr(index) \
+#define __ia64_get_ibr(index) \
({ \
__u64 ia64_intri_res; \
asm volatile ("mov %0=ibr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
ia64_intri_res; \
})
-#define ia64_get_pkr(index) \
+#define __ia64_get_pkr(index) \
({ \
__u64 ia64_intri_res; \
asm volatile ("mov %0=pkr[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
ia64_intri_res; \
})
-#define ia64_get_pmc(index) \
+#define __ia64_get_pmc(index) \
({ \
__u64 ia64_intri_res; \
asm volatile ("mov %0=pmc[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
@@ -473,48 +473,48 @@ register unsigned long ia64_r13 asm ("r13") __used;
})
-#define ia64_get_pmd(index) \
+#define __ia64_get_pmd(index) \
({ \
__u64 ia64_intri_res; \
asm volatile ("mov %0=pmd[%1]" : "=r"(ia64_intri_res) : "r"(index)); \
ia64_intri_res; \
})
-#define ia64_get_rr(index) \
+#define __ia64_get_rr(index) \
({ \
__u64 ia64_intri_res; \
asm volatile ("mov %0=rr[%1]" : "=r"(ia64_intri_res) : "r" (index)); \
ia64_intri_res; \
})
-#define ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory")
+#define __ia64_fc(addr) asm volatile ("fc %0" :: "r"(addr) : "memory")
#define ia64_sync_i() asm volatile (";; sync.i" ::: "memory")
-#define ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory")
-#define ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory")
+#define __ia64_ssm(mask) asm volatile ("ssm %0":: "i"((mask)) : "memory")
+#define __ia64_rsm(mask) asm volatile ("rsm %0":: "i"((mask)) : "memory")
#define ia64_sum(mask) asm volatile ("sum %0":: "i"((mask)) : "memory")
#define ia64_rum(mask) asm volatile ("rum %0":: "i"((mask)) : "memory")
-#define ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr))
+#define __ia64_ptce(addr) asm volatile ("ptc.e %0" :: "r"(addr))
-#define ia64_ptcga(addr, size) \
+#define __ia64_ptcga(addr, size) \
do { \
asm volatile ("ptc.ga %0,%1" :: "r"(addr), "r"(size) : "memory"); \
ia64_dv_serialize_data(); \
} while (0)
-#define ia64_ptcl(addr, size) \
+#define __ia64_ptcl(addr, size) \
do { \
asm volatile ("ptc.l %0,%1" :: "r"(addr), "r"(size) : "memory"); \
ia64_dv_serialize_data(); \
} while (0)
-#define ia64_ptri(addr, size) \
+#define __ia64_ptri(addr, size) \
asm volatile ("ptr.i %0,%1" :: "r"(addr), "r"(size) : "memory")
-#define ia64_ptrd(addr, size) \
+#define __ia64_ptrd(addr, size) \
asm volatile ("ptr.d %0,%1" :: "r"(addr), "r"(size) : "memory")
/* Values for lfhint in ia64_lfetch and ia64_lfetch_fault */
@@ -596,7 +596,7 @@ do { \
} \
})
-#define ia64_intrin_local_irq_restore(x) \
+#define __ia64_intrin_local_irq_restore(x) \
do { \
asm volatile (";; cmp.ne p6,p7=%0,r0;;" \
"(p6) ssm psr.i;" \
diff --git a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h
index a520d10..83ee398 100644
--- a/include/asm-ia64/intel_intrin.h
+++ b/include/asm-ia64/intel_intrin.h
@@ -16,8 +16,8 @@
* intrinsic
*/
-#define ia64_getreg __getReg
-#define ia64_setreg __setReg
+#define __ia64_getreg __getReg
+#define __ia64_setreg __setReg
#define ia64_hint __hint
#define ia64_hint_pause __hint_pause
@@ -33,16 +33,16 @@
#define ia64_getf_exp __getf_exp
#define ia64_shrp _m64_shrp
-#define ia64_tpa __tpa
+#define __ia64_tpa __tpa
#define ia64_invala __invala
#define ia64_invala_gr __invala_gr
#define ia64_invala_fr __invala_fr
#define ia64_nop __nop
#define ia64_sum __sum
-#define ia64_ssm __ssm
+#define __ia64_ssm __ssm
#define ia64_rum __rum
-#define ia64_rsm __rsm
-#define ia64_fc __fc
+#define __ia64_rsm __rsm
+#define __ia64_fc __fc
#define ia64_ldfs __ldfs
#define ia64_ldfd __ldfd
@@ -80,24 +80,24 @@
#define __ia64_set_dbr(index, val) \
__setIndReg(_IA64_REG_INDR_DBR, index, val)
-#define ia64_set_ibr(index, val) \
+#define __ia64_set_ibr(index, val) \
__setIndReg(_IA64_REG_INDR_IBR, index, val)
-#define ia64_set_pkr(index, val) \
+#define __ia64_set_pkr(index, val) \
__setIndReg(_IA64_REG_INDR_PKR, index, val)
-#define ia64_set_pmc(index, val) \
+#define __ia64_set_pmc(index, val) \
__setIndReg(_IA64_REG_INDR_PMC, index, val)
-#define ia64_set_pmd(index, val) \
+#define __ia64_set_pmd(index, val) \
__setIndReg(_IA64_REG_INDR_PMD, index, val)
-#define ia64_set_rr(index, val) \
+#define __ia64_set_rr(index, val) \
__setIndReg(_IA64_REG_INDR_RR, index, val)
-#define ia64_get_cpuid(index) __getIndReg(_IA64_REG_INDR_CPUID, index)
+#define __ia64_get_cpuid(index) __getIndReg(_IA64_REG_INDR_CPUID, index)
#define __ia64_get_dbr(index) __getIndReg(_IA64_REG_INDR_DBR, index)
-#define ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index)
-#define ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index)
-#define ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index)
-#define ia64_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index)
-#define ia64_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index)
+#define __ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index)
+#define __ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index)
+#define __ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index)
+#define __ia64_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index)
+#define __ia64_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index)
#define ia64_srlz_d __dsrlz
#define ia64_srlz_i __isrlz
@@ -119,18 +119,18 @@
#define ia64_ld8_acq __ld8_acq
#define ia64_sync_i __synci
-#define ia64_thash __thash
-#define ia64_ttag __ttag
-#define ia64_itcd __itcd
-#define ia64_itci __itci
-#define ia64_itrd __itrd
-#define ia64_itri __itri
-#define ia64_ptce __ptce
-#define ia64_ptcl __ptcl
-#define ia64_ptcg __ptcg
-#define ia64_ptcga __ptcga
-#define ia64_ptri __ptri
-#define ia64_ptrd __ptrd
+#define __ia64_thash __thash
+#define __ia64_ttag __ttag
+#define __ia64_itcd __itcd
+#define __ia64_itci __itci
+#define __ia64_itrd __itrd
+#define __ia64_itri __itri
+#define __ia64_ptce __ptce
+#define __ia64_ptcl __ptcl
+#define __ia64_ptcg __ptcg
+#define __ia64_ptcga __ptcga
+#define __ia64_ptri __ptri
+#define __ia64_ptrd __ptrd
#define ia64_dep_mi _m64_dep_mi
/* Values for lfhint in __lfetch and __lfetch_fault */
@@ -145,13 +145,13 @@
#define ia64_lfetch_fault __lfetch_fault
#define ia64_lfetch_fault_excl __lfetch_fault_excl
-#define ia64_intrin_local_irq_restore(x) \
+#define __ia64_intrin_local_irq_restore(x) \
do { \
if ((x) != 0) { \
- ia64_ssm(IA64_PSR_I); \
+ __ia64_ssm(IA64_PSR_I); \
ia64_srlz_d(); \
} else { \
- ia64_rsm(IA64_PSR_I); \
+ __ia64_rsm(IA64_PSR_I); \
} \
} while (0)
diff --git a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h
index 5800ad0..4edf6de 100644
--- a/include/asm-ia64/intrinsics.h
+++ b/include/asm-ia64/intrinsics.h
@@ -18,15 +18,15 @@
# include <asm/gcc_intrin.h>
#endif
-#define ia64_get_psr_i() (ia64_getreg(_IA64_REG_PSR) & IA64_PSR_I)
+#define __ia64_get_psr_i() (__ia64_getreg(_IA64_REG_PSR) & IA64_PSR_I)
-#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \
+#define __ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \
do { \
- ia64_set_rr(0x0000000000000000UL, (val0)); \
- ia64_set_rr(0x2000000000000000UL, (val1)); \
- ia64_set_rr(0x4000000000000000UL, (val2)); \
- ia64_set_rr(0x6000000000000000UL, (val3)); \
- ia64_set_rr(0x8000000000000000UL, (val4)); \
+ __ia64_set_rr(0x0000000000000000UL, (val0)); \
+ __ia64_set_rr(0x2000000000000000UL, (val1)); \
+ __ia64_set_rr(0x4000000000000000UL, (val2)); \
+ __ia64_set_rr(0x6000000000000000UL, (val3)); \
+ __ia64_set_rr(0x8000000000000000UL, (val4)); \
} while (0)
/*
diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h
index 09c14ae..8261dad 100644
--- a/include/asm-ia64/privop.h
+++ b/include/asm-ia64/privop.h
@@ -16,6 +16,42 @@
/* fallback for native case */
+#ifndef IA64_PARAVIRTUALIZED_PRIVOP
+#ifndef __ASSEMBLY
+#define ia64_getreg __ia64_getreg
+#define ia64_setreg __ia64_setreg
+#define ia64_hint __ia64_hint
+#define ia64_thash __ia64_thash
+#define ia64_itci __ia64_itci
+#define ia64_itcd __ia64_itcd
+#define ia64_itri __ia64_itri
+#define ia64_itrd __ia64_itrd
+#define ia64_tpa __ia64_tpa
+#define ia64_set_ibr __ia64_set_ibr
+#define ia64_set_pkr __ia64_set_pkr
+#define ia64_set_pmc __ia64_set_pmc
+#define ia64_set_pmd __ia64_set_pmd
+#define ia64_set_rr __ia64_set_rr
+#define ia64_get_cpuid __ia64_get_cpuid
+#define ia64_get_ibr __ia64_get_ibr
+#define ia64_get_pkr __ia64_get_pkr
+#define ia64_get_pmc __ia64_get_pmc
+#define ia64_get_pmd __ia64_get_pmd
+#define ia64_get_rr __ia64_get_rr
+#define ia64_fc __ia64_fc
+#define ia64_ssm __ia64_ssm
+#define ia64_rsm __ia64_rsm
+#define ia64_ptce __ia64_ptce
+#define ia64_ptcga __ia64_ptcga
+#define ia64_ptcl __ia64_ptcl
+#define ia64_ptri __ia64_ptri
+#define ia64_ptrd __ia64_ptrd
+#define ia64_get_psr_i __ia64_get_psr_i
+#define ia64_intrin_local_irq_restore __ia64_intrin_local_irq_restore
+#define ia64_set_rr0_to_rr4 __ia64_set_rr0_to_rr4
+#endif /* !__ASSEMBLY */
+#endif /* !IA64_PARAVIRTUALIZED_PRIVOP */
+
#ifndef IA64_PARAVIRTUALIZED_ENTRY
#define ia64_switch_to __ia64_switch_to
#define ia64_leave_syscall __ia64_leave_syscall
diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h
index 0fa8aa6..3caa7e9 100644
--- a/include/asm-ia64/xen/privop.h
+++ b/include/asm-ia64/xen/privop.h
@@ -70,6 +70,495 @@
#define XSI_IHA (XSI_BASE + XSI_IHA_OFS)
#endif
+#ifndef __ASSEMBLY__
+#define XEN_HYPER_SSM_I asm("break %0" : : "i" (HYPERPRIVOP_SSM_I))
+#define XEN_HYPER_GET_IVR asm("break %0" : : "i" (HYPERPRIVOP_GET_IVR))
+
+/************************************************/
+/* Instructions paravirtualized for correctness */
+/************************************************/
+
+/* "fc" and "thash" are privilege-sensitive instructions, meaning they
+ * may have different semantics depending on whether they are executed
+ * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't
+ * be allowed to execute directly, lest incorrect semantics result. */
+#ifdef ASM_SUPPORTED
+static inline void
+xen_fc(unsigned long addr)
+{
+ register __u64 __addr asm ("r8") = addr;
+ asm volatile ("break %0":: "i"(HYPERPRIVOP_FC), "r"(__addr));
+}
+
+static inline unsigned long
+xen_thash(unsigned long addr)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __addr asm ("r8") = addr;
+ asm volatile ("break %1":
+ "=r"(ia64_intri_res):
+ "i"(HYPERPRIVOP_THASH), "0"(__addr));
+ return ia64_intri_res;
+}
+#else
+extern void xen_fc(unsigned long addr);
+extern unsigned long xen_thash(unsigned long addr);
+#endif
+
+/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag"
+ * is not currently used (though it may be in a long-format VHPT system!)
+ * and the semantics of cover only change if psr.ic is off which is very
+ * rare (and currently non-existent outside of assembly code */
+
+/* There are also privilege-sensitive registers. These registers are
+ * readable at any privilege level but only writable at PL0. */
+#ifdef ASM_SUPPORTED
+static inline unsigned long
+xen_get_cpuid(int index)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __index asm ("r8") = index;
+ asm volatile ("break %1":
+ "=r"(ia64_intri_res):
+ "i"(HYPERPRIVOP_GET_CPUID), "0"(__index));
+ return ia64_intri_res;
+}
+
+static inline unsigned long
+xen_get_pmd(int index)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __index asm ("r8") = index;
+ asm volatile ("break %1":
+ "=r"(ia64_intri_res):
+ "i"(HYPERPRIVOP_GET_PMD), "0O"(__index));
+ return ia64_intri_res;
+}
+#else
+extern unsigned long xen_get_cpuid(int index);
+extern unsigned long xen_get_pmd(int index);
+#endif
+
+#ifdef ASM_SUPPORTED
+static inline unsigned long
+xen_get_eflag(void)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ asm volatile ("break %1":
+ "=r"(ia64_intri_res): "i"(HYPERPRIVOP_GET_EFLAG));
+ return ia64_intri_res;
+}
+
+static inline void
+xen_set_eflag(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile ("break %0":: "i"(HYPERPRIVOP_SET_EFLAG), "r"(__val));
+}
+#else
+extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */
+extern void xen_set_eflag(unsigned long); /* see xen_ia64_setreg */
+#endif
+
+/************************************************/
+/* Instructions paravirtualized for performance */
+/************************************************/
+
+/* Xen uses memory-mapped virtual privileged registers for access to many
+ * performance-sensitive privileged registers. Some, like the processor
+ * status register (psr), are broken up into multiple memory locations.
+ * Others, like "pend", are abstractions based on privileged registers.
+ * "Pend" is guaranteed to be set if reading cr.ivr would return a
+ * (non-spurious) interrupt. */
+#define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE)
+
+#define XSI_PSR_I \
+ (*XEN_MAPPEDREGS->interrupt_mask_addr)
+#define xen_get_virtual_psr_i() \
+ (!XSI_PSR_I)
+#define xen_set_virtual_psr_i(_val) \
+ ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; })
+#define xen_set_virtual_psr_ic(_val) \
+ ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; })
+#define xen_get_virtual_pend() \
+ (*(((uint8_t *)XEN_MAPPEDREGS->interrupt_mask_addr) - 1))
+
+/* Hyperprivops are "break" instructions with a well-defined API.
+ * In particular, the virtual psr.ic bit must be off; in this way
+ * it is guaranteed to never conflict with a linux break instruction.
+ * Normally, this is done in a xen stub but this one is frequent enough
+ * that we inline it */
+#define xen_hyper_ssm_i() \
+({ \
+ XEN_HYPER_SSM_I; \
+})
+
+/* turning off interrupts can be paravirtualized simply by writing
+ * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */
+#define xen_rsm_i() \
+do { \
+ xen_set_virtual_psr_i(0); \
+ barrier(); \
+} while (0)
+
+/* turning on interrupts is a bit more complicated.. write to the
+ * memory-mapped virtual psr.i bit first (to avoid race condition),
+ * then if any interrupts were pending, we have to execute a hyperprivop
+ * to ensure the pending interrupt gets delivered; else we're done! */
+#define xen_ssm_i() \
+do { \
+ int old = xen_get_virtual_psr_i(); \
+ xen_set_virtual_psr_i(1); \
+ barrier(); \
+ if (!old && xen_get_virtual_pend()) \
+ xen_hyper_ssm_i(); \
+} while (0)
+
+#define xen_ia64_intrin_local_irq_restore(x) \
+do { \
+ if (is_running_on_xen()) { \
+ if ((x) & IA64_PSR_I) \
+ xen_ssm_i(); \
+ else \
+ xen_rsm_i(); \
+ } else { \
+ __ia64_intrin_local_irq_restore((x)); \
+ } \
+} while (0)
+
+#define xen_get_psr_i() \
+({ \
+ \
+ (is_running_on_xen()) ? \
+ (xen_get_virtual_psr_i() ? IA64_PSR_I : 0) \
+ : __ia64_get_psr_i() \
+})
+
+#define xen_ia64_ssm(mask) \
+do { \
+ if ((mask) == IA64_PSR_I) { \
+ if (is_running_on_xen()) \
+ xen_ssm_i(); \
+ else \
+ __ia64_ssm(mask); \
+ } else { \
+ __ia64_ssm(mask); \
+ } \
+} while (0)
+
+#define xen_ia64_rsm(mask) \
+do { \
+ if ((mask) == IA64_PSR_I) { \
+ if (is_running_on_xen()) \
+ xen_rsm_i(); \
+ else \
+ __ia64_rsm(mask); \
+ } else { \
+ __ia64_rsm(mask); \
+ } \
+} while (0)
+
+/* Although all privileged operations can be left to trap and will
+ * be properly handled by Xen, some are frequent enough that we use
+ * hyperprivops for performance. */
+
+#ifndef ASM_SUPPORTED
+extern unsigned long xen_get_psr(void);
+extern unsigned long xen_get_ivr(void);
+extern unsigned long xen_get_tpr(void);
+extern void xen_set_itm(unsigned long);
+extern void xen_set_tpr(unsigned long);
+extern void xen_eoi(unsigned long);
+extern void xen_set_rr(unsigned long index, unsigned long val);
+extern unsigned long xen_get_rr(unsigned long index);
+extern void xen_set_kr(unsigned long index, unsigned long val);
+extern void xen_ptcga(unsigned long addr, unsigned long size);
+#else
+static inline unsigned long
+xen_get_psr(void)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ asm volatile ("break %1":
+ "=r"(ia64_intri_res): "i"(HYPERPRIVOP_GET_PSR));
+ return ia64_intri_res;
+}
+
+static inline unsigned long
+xen_get_ivr(void)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ asm volatile ("break %1":
+ "=r"(ia64_intri_res): "i"(HYPERPRIVOP_GET_IVR));
+ return ia64_intri_res;
+}
+
+static inline unsigned long
+xen_get_tpr(void)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ asm volatile ("break %1":
+ "=r"(ia64_intri_res): "i"(HYPERPRIVOP_GET_TPR));
+ return ia64_intri_res;
+}
+
+static inline void
+xen_set_tpr(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile ("break %0"::
+ "i"(HYPERPRIVOP_GET_TPR), "r"(__val));
+}
+
+static inline void
+xen_eoi(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile ("break %0"::
+ "i"(HYPERPRIVOP_EOI), "r"(__val));
+}
+
+static inline void
+xen_set_itm(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile ("break %0":: "i"(HYPERPRIVOP_SET_ITM), "r"(__val));
+}
+
+static inline void
+xen_ptcga(unsigned long addr, unsigned long size)
+{
+ register __u64 __addr asm ("r8") = addr;
+ register __u64 __size asm ("r9") = size;
+ asm volatile ("break %0"::
+ "i"(HYPERPRIVOP_PTC_GA), "r"(__addr), "r"(__size));
+}
+
+static inline unsigned long
+xen_get_rr(unsigned long index)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __index asm ("r8") = index;
+ asm volatile ("break %1":
+ "=r"(ia64_intri_res):
+ "i"(HYPERPRIVOP_GET_RR), "0"(__index));
+ return ia64_intri_res;
+}
+
+static inline void
+xen_set_rr(unsigned long index, unsigned long val)
+{
+ register __u64 __index asm ("r8") = index;
+ register __u64 __val asm ("r9") = val;
+ asm volatile ("break %0"::
+ "i"(HYPERPRIVOP_SET_RR), "r"(__index), "r"(__val));
+}
+
+static inline void
+xen_set_rr0_to_rr4(unsigned long val0, unsigned long val1,
+ unsigned long val2, unsigned long val3, unsigned long val4)
+{
+ register __u64 __val0 asm ("r8") = val0;
+ register __u64 __val1 asm ("r9") = val1;
+ register __u64 __val2 asm ("r10") = val2;
+ register __u64 __val3 asm ("r11") = val3;
+ register __u64 __val4 asm ("r14") = val4;
+ asm volatile ("break %0" ::
+ "i"(HYPERPRIVOP_SET_RR0_TO_RR4),
+ "r"(__val0), "r"(__val1),
+ "r"(__val2), "r"(__val3), "r"(__val4));
+}
+
+static inline void
+xen_set_kr(unsigned long index, unsigned long val)
+{
+ register __u64 __index asm ("r8") = index;
+ register __u64 __val asm ("r9") = val;
+ asm volatile ("break %0"::
+ "i"(HYPERPRIVOP_SET_KR), "r"(__index), "r"(__val));
+}
+#endif
+
+/* Note: It may look wrong to test for is_running_on_xen() in each case.
+ * However regnum is always a constant so, as written, the compiler
+ * eliminates the switch statement, whereas is_running_on_xen() must be
+ * tested dynamically. */
+#define xen_ia64_getreg(regnum) \
+({ \
+ __u64 ia64_intri_res; \
+ \
+ switch (regnum) { \
+ case _IA64_REG_PSR: \
+ ia64_intri_res = (is_running_on_xen()) ? \
+ xen_get_psr() : \
+ __ia64_getreg(regnum); \
+ break; \
+ case _IA64_REG_CR_IVR: \
+ ia64_intri_res = (is_running_on_xen()) ? \
+ xen_get_ivr() : \
+ __ia64_getreg(regnum); \
+ break; \
+ case _IA64_REG_CR_TPR: \
+ ia64_intri_res = (is_running_on_xen()) ? \
+ xen_get_tpr() : \
+ __ia64_getreg(regnum); \
+ break; \
+ case _IA64_REG_AR_EFLAG: \
+ ia64_intri_res = (is_running_on_xen()) ? \
+ xen_get_eflag() : \
+ __ia64_getreg(regnum); \
+ break; \
+ default: \
+ ia64_intri_res = __ia64_getreg(regnum); \
+ break; \
+ } \
+ ia64_intri_res; \
+})
+
+#define xen_ia64_setreg(regnum, val) \
+({ \
+ switch (regnum) { \
+ case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: \
+ (is_running_on_xen()) ? \
+ xen_set_kr(((regnum)-_IA64_REG_AR_KR0), (val)) :\
+ __ia64_setreg((regnum), (val)); \
+ break; \
+ case _IA64_REG_CR_ITM: \
+ (is_running_on_xen()) ? \
+ xen_set_itm(val) : \
+ __ia64_setreg((regnum), (val)); \
+ break; \
+ case _IA64_REG_CR_TPR: \
+ (is_running_on_xen()) ? \
+ xen_set_tpr(val) : \
+ __ia64_setreg((regnum), (val)); \
+ break; \
+ case _IA64_REG_CR_EOI: \
+ (is_running_on_xen()) ? \
+ xen_eoi(val) : \
+ __ia64_setreg((regnum), (val)); \
+ break; \
+ case _IA64_REG_AR_EFLAG: \
+ (is_running_on_xen()) ? \
+ xen_set_eflag(val) : \
+ __ia64_setreg((regnum), (val)); \
+ break; \
+ default: \
+ __ia64_setreg((regnum), (val)); \
+ break; \
+ } \
+})
+
+#if defined(ASM_SUPPORTED) && !defined(CONFIG_PARAVIRT_ALT)
+
+#define IA64_PARAVIRTUALIZED_PRIVOP
+
+#define ia64_fc(addr) \
+do { \
+ if (is_running_on_xen()) \
+ xen_fc((unsigned long)(addr)); \
+ else \
+ __ia64_fc(addr); \
+} while (0)
+
+#define ia64_thash(addr) \
+({ \
+ unsigned long ia64_intri_res; \
+ if (is_running_on_xen()) \
+ ia64_intri_res = \
+ xen_thash((unsigned long)(addr)); \
+ else \
+ ia64_intri_res = __ia64_thash(addr); \
+ ia64_intri_res; \
+})
+
+#define ia64_get_cpuid(i) \
+({ \
+ unsigned long ia64_intri_res; \
+ if (is_running_on_xen()) \
+ ia64_intri_res = xen_get_cpuid(i); \
+ else \
+ ia64_intri_res = __ia64_get_cpuid(i); \
+ ia64_intri_res; \
+})
+
+#define ia64_get_pmd(i) \
+({ \
+ unsigned long ia64_intri_res; \
+ if (is_running_on_xen()) \
+ ia64_intri_res = xen_get_pmd(i); \
+ else \
+ ia64_intri_res = __ia64_get_pmd(i); \
+ ia64_intri_res; \
+})
+
+
+#define ia64_ptcga(addr, size) \
+do { \
+ if (is_running_on_xen()) \
+ xen_ptcga((addr), (size)); \
+ else \
+ __ia64_ptcga((addr), (size)); \
+} while (0)
+
+#define ia64_set_rr(index, val) \
+do { \
+ if (is_running_on_xen()) \
+ xen_set_rr((index), (val)); \
+ else \
+ __ia64_set_rr((index), (val)); \
+} while (0)
+
+#define ia64_get_rr(index) \
+({ \
+ __u64 ia64_intri_res; \
+ if (is_running_on_xen()) \
+ ia64_intri_res = xen_get_rr((index)); \
+ else \
+ ia64_intri_res = __ia64_get_rr((index)); \
+ ia64_intri_res; \
+})
+
+#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \
+do { \
+ if (is_running_on_xen()) \
+ xen_set_rr0_to_rr4((val0), (val1), (val2), \
+ (val3), (val4)); \
+ else \
+ __ia64_set_rr0_to_rr4((val0), (val1), (val2), \
+ (val3), (val4)); \
+} while (0)
+
+#define ia64_getreg xen_ia64_getreg
+#define ia64_setreg xen_ia64_setreg
+#define ia64_ssm xen_ia64_ssm
+#define ia64_rsm xen_ia64_rsm
+#define ia64_intrin_local_irq_restore xen_ia64_intrin_local_irq_restore
+#define ia64_get_psr_i xen_get_psr_i
+
+/* the remainder of these are not performance-sensitive so its
+ * OK to not paravirtualize and just take a privop trap and emulate */
+#define ia64_hint __ia64_hint
+#define ia64_set_pmd __ia64_set_pmd
+#define ia64_itci __ia64_itci
+#define ia64_itcd __ia64_itcd
+#define ia64_itri __ia64_itri
+#define ia64_itrd __ia64_itrd
+#define ia64_tpa __ia64_tpa
+#define ia64_set_ibr __ia64_set_ibr
+#define ia64_set_pkr __ia64_set_pkr
+#define ia64_set_pmc __ia64_set_pmc
+#define ia64_get_ibr __ia64_get_ibr
+#define ia64_get_pkr __ia64_get_pkr
+#define ia64_get_pmc __ia64_get_pmc
+#define ia64_ptce __ia64_ptce
+#define ia64_ptcl __ia64_ptcl
+#define ia64_ptri __ia64_ptri
+#define ia64_ptrd __ia64_ptrd
+
+#endif /* ASM_SUPPORTED && !CONFIG_PARAVIRT_ALT */
+
+#endif /* !__ASSEMBLY__ */
+
/* these routines utilize privilege-sensitive or performance-sensitive
* privileged instructions so the code must be replaced with
* paravirtualized versions */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 11/28] ia64: introduce basic facilities for binary patching.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (9 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 10/28] RFC: ia64/xen: introduce xen paravirtualized intrinsic operations for privileged instruction yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 12/28] RFC: ia64/xen: xen privileged instruction intrinsics " yamahata
` (21 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0011-ia64-introduce-basic-facilities-for-binary-patching.patch --]
[-- Type: text/plain, Size: 28727 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/Kconfig | 72 +++++++++++++
arch/ia64/kernel/Makefile | 5 +
arch/ia64/kernel/paravirt_alt.c | 118 ++++++++++++++++++++++
arch/ia64/kernel/paravirt_core.c | 201 +++++++++++++++++++++++++++++++++++++
arch/ia64/kernel/paravirt_entry.c | 99 ++++++++++++++++++
arch/ia64/kernel/paravirt_nop.c | 49 +++++++++
arch/ia64/kernel/vmlinux.lds.S | 35 +++++++
include/asm-ia64/module.h | 6 +
include/asm-ia64/paravirt_alt.h | 82 +++++++++++++++
include/asm-ia64/paravirt_core.h | 54 ++++++++++
include/asm-ia64/paravirt_entry.h | 62 +++++++++++
include/asm-ia64/paravirt_nop.h | 46 +++++++++
12 files changed, 829 insertions(+), 0 deletions(-)
create mode 100644 arch/ia64/kernel/paravirt_alt.c
create mode 100644 arch/ia64/kernel/paravirt_core.c
create mode 100644 arch/ia64/kernel/paravirt_entry.c
create mode 100644 arch/ia64/kernel/paravirt_nop.c
create mode 100644 include/asm-ia64/paravirt_alt.h
create mode 100644 include/asm-ia64/paravirt_core.h
create mode 100644 include/asm-ia64/paravirt_entry.h
create mode 100644 include/asm-ia64/paravirt_nop.h
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index dff9edf..bc84008 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -110,6 +110,78 @@ config AUDIT_ARCH
bool
default y
+menuconfig PARAVIRT_GUEST
+ bool "Paravirtualized guest support"
+ help
+ Say Y here to get to see options related to running Linux under
+ various hypervisors. This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and disabled.
+
+if PARAVIRT_GUEST
+
+config PARAVIRT
+ bool
+ default y
+ help
+ This changes the kernel so it can modify itself when it is run
+ under a hypervisor, potentially improving performance significantly
+ over full virtualization. However, when run without a hypervisor
+ the kernel is theoretically slower and slightly larger.
+
+config PARAVIRT_ALT
+ bool "paravirt_alt binary patching infrastructure"
+ depends on PARAVIRT
+ default y
+ help
+ The binary patching infratstructure to replace some privileged
+ instructions with hypervisor specific instrutions.
+ There are several sensitive(i.e. non-virtualizable) instructions and
+ performance critical privileged instructions which Xen
+ paravirtualize as hyperprivops.
+ For transparent paravirtualization (i.e. single binary should run
+ on both baremetal and xen environment), xenLinux/IA64 needs
+ something like "if (is_running_on_xen()) {} else {}" where
+ is_running_on_xen() is determined at boot time.
+ This configuration tries to eliminate the overheads for hyperprivops
+ by annotating such instructions and replacing them with hyperprivops
+ at boot time.
+
+config PARAVIRT_ENTRY
+ bool "paravirt entry"
+ depends on PARAVIRT
+ default y
+ help
+ The entry point hooking infrastructure to change the execution path
+ at the boot time.
+ There are several paravirtualized paths in hand coded assembly code
+ which isn't binary patched easily by the paravirt_alt infrastructure.
+ E.g. ia64_switch_to, ia64_leave_syscall, ia64_leave_kernel and
+ ia64_pal_call_static.
+ For those hand written assembly code, change the execution path
+ by hooking them and jumping to hand paravirtualized code.
+
+config PARAVIRT_NOP_B_PATCH
+ bool "paravirt branch if native"
+ depends on PARAVIRT
+ default y
+ help
+ paravirt branch if native
+ There are several paravirtualized paths in hand coded assembly code.
+ For transparent paravirtualization, there are codes like
+ GLOBAL_ENTRY(xen_xxx)
+ 'movl reg=running_on_xen;;'
+ 'ld4 reg=[reg];;'
+ 'cmp.e1 pred,p0=reg,r0'
+ '(pred) br.cond.sptk.many <native_xxx>;;'
+ To reduce overhead when running on bare metal, just
+ "br.cond.sptk.many <native_xxx>" and replace it with 'nop.b 0'
+ when running on xen.
+
+#source "arch/ia64/xen/Kconfig"
+
+endif
+
choice
prompt "System type"
default IA64_GENERIC
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 33e5a59..d0e22bb 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -36,6 +36,11 @@ obj-$(CONFIG_PCI_MSI) += msi_ia64.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
obj-$(CONFIG_IA64_MC_ERR_INJECT)+= err_inject.o
+obj-$(CONFIG_PARAVIRT) += paravirt_core.o
+obj-$(CONFIG_PARAVIRT_ALT) += paravirt_alt.o
+obj-$(CONFIG_PARAVIRT_ENTRY) += paravirt_entry.o paravirtentry.o
+obj-$(CONFIG_PARAVIRT_NOP_B_PATCH) += paravirt_nop.o
+
obj-$(CONFIG_IA64_ESI) += esi.o
ifneq ($(CONFIG_IA64_ESI),)
obj-y += esi_stub.o # must be in kernel proper
diff --git a/arch/ia64/kernel/paravirt_alt.c b/arch/ia64/kernel/paravirt_alt.c
new file mode 100644
index 0000000..d0a34a7
--- /dev/null
+++ b/arch/ia64/kernel/paravirt_alt.c
@@ -0,0 +1,118 @@
+/******************************************************************************
+ * linux/arch/ia64/xen/paravirt_alt.c
+ *
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/paravirt_core.h>
+
+extern const char nop_bundle[];
+extern const unsigned long nop_bundle_size;
+
+static void __init_or_module
+fill_nop(void *sbundle, void *ebundle)
+{
+ void *bundle = sbundle;
+ BUG_ON((((unsigned long)sbundle) % sizeof(bundle_t)) != 0);
+ BUG_ON((((unsigned long)ebundle) % sizeof(bundle_t)) != 0);
+
+ while (bundle < ebundle) {
+ memcpy(bundle, nop_bundle, nop_bundle_size);
+
+ bundle += nop_bundle_size;
+ }
+}
+
+void __init_or_module
+paravirt_alt_bundle_patch_apply(struct paravirt_alt_bundle_patch *start,
+ struct paravirt_alt_bundle_patch *end,
+ unsigned long(*patch)(void *sbundle,
+ void *ebundle,
+ unsigned long type))
+{
+ struct paravirt_alt_bundle_patch *p;
+
+ for (p = start; p < end; p++) {
+ unsigned long used;
+
+ used = (*patch)(p->sbundle, p->ebundle, p->type);
+ if (used == 0)
+ continue;
+
+ fill_nop(p->sbundle + used, p->ebundle);
+ paravirt_flush_i_cache_range(p->sbundle,
+ p->ebundle - p->sbundle);
+ }
+ ia64_sync_i();
+ ia64_srlz_i();
+}
+
+/*
+ * nop.i, nop.m, nop.f instruction are same format.
+ * but nop.b has differennt format.
+ * This doesn't support nop.b for now.
+ */
+static void __init_or_module
+fill_nop_inst(unsigned long stag, unsigned long etag)
+{
+ extern const bundle_t nop_mfi_inst_bundle[];
+ unsigned long tag;
+ const cmp_inst_t nop_inst = paravirt_read_slot0(nop_mfi_inst_bundle);
+
+ for (tag = stag; tag < etag; tag = paravirt_get_next_tag(tag))
+ paravirt_write_inst(tag, nop_inst);
+}
+
+void __init_or_module
+paravirt_alt_inst_patch_apply(struct paravirt_alt_inst_patch *start,
+ struct paravirt_alt_inst_patch *end,
+ unsigned long (*patch)(unsigned long stag,
+ unsigned long etag,
+ unsigned long type))
+{
+ struct paravirt_alt_inst_patch *p;
+
+ for (p = start; p < end; p++) {
+ unsigned long tag;
+ bundle_t *sbundle;
+ bundle_t *ebundle;
+
+ tag = (*patch)(p->stag, p->etag, p->type);
+ if (tag == p->stag)
+ continue;
+
+ fill_nop_inst(tag, p->etag);
+ sbundle = paravirt_get_bundle(p->stag);
+ ebundle = paravirt_get_bundle(p->etag) + 1;
+ paravirt_flush_i_cache_range(sbundle, (ebundle - sbundle) *
+ sizeof(bundle_t));
+ }
+ ia64_sync_i();
+ ia64_srlz_i();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/arch/ia64/kernel/paravirt_core.c b/arch/ia64/kernel/paravirt_core.c
new file mode 100644
index 0000000..6b7c70f
--- /dev/null
+++ b/arch/ia64/kernel/paravirt_core.c
@@ -0,0 +1,201 @@
+/******************************************************************************
+ * linux/arch/ia64/xen/paravirt_core.c
+ *
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/paravirt_core.h>
+
+/*
+ * flush_icache_range() can't be used here.
+ * we are here before cpu_init() which initializes
+ * ia64_i_cache_stride_shift. flush_icache_range() uses it.
+ */
+void __init_or_module
+paravirt_flush_i_cache_range(const void *instr, unsigned long size)
+{
+ unsigned long i;
+
+ for (i = 0; i < size; i += sizeof(bundle_t))
+ asm volatile ("fc.i %0":: "r"(instr + i): "memory");
+}
+
+bundle_t* __init_or_module
+paravirt_get_bundle(unsigned long tag)
+{
+ return (bundle_t *)(tag & ~3UL);
+}
+
+unsigned long __init_or_module
+paravirt_get_slot(unsigned long tag)
+{
+ return tag & 3UL;
+}
+
+#if 0
+unsigned long __init_or_module
+paravirt_get_num_inst(unsigned long stag, unsigned long etag)
+{
+ bundle_t *sbundle = paravirt_get_bundle(stag);
+ unsigned long sslot = paravirt_get_slot(stag);
+ bundle_t *ebundle = paravirt_get_bundle(etag);
+ unsigned long eslot = paravirt_get_slot(etag);
+
+ return (ebundle - sbundle) * 3 + eslot - sslot + 1;
+}
+#endif
+
+unsigned long __init_or_module
+paravirt_get_next_tag(unsigned long tag)
+{
+ unsigned long slot = paravirt_get_slot(tag);
+
+ switch (slot) {
+ case 0:
+ case 1:
+ return tag + 1;
+ case 2: {
+ bundle_t *bundle = paravirt_get_bundle(tag);
+ return (unsigned long)(bundle + 1);
+ }
+ default:
+ BUG();
+ }
+ /* NOTREACHED */
+}
+
+cmp_inst_t __init_or_module
+paravirt_read_slot0(const bundle_t *bundle)
+{
+ cmp_inst_t inst;
+ inst.l = bundle->quad0.slot0;
+ return inst;
+}
+
+cmp_inst_t __init_or_module
+paravirt_read_slot1(const bundle_t *bundle)
+{
+ cmp_inst_t inst;
+ inst.l = bundle->quad0.slot1_p0 |
+ ((unsigned long long)bundle->quad1.slot1_p1 << 18UL);
+ return inst;
+}
+
+cmp_inst_t __init_or_module
+paravirt_read_slot2(const bundle_t *bundle)
+{
+ cmp_inst_t inst;
+ inst.l = bundle->quad1.slot2;
+ return inst;
+}
+
+cmp_inst_t __init_or_module
+paravirt_read_inst(unsigned long tag)
+{
+ bundle_t *bundle = paravirt_get_bundle(tag);
+ unsigned long slot = paravirt_get_slot(tag);
+
+ switch (slot) {
+ case 0:
+ return paravirt_read_slot0(bundle);
+ case 1:
+ return paravirt_read_slot1(bundle);
+ case 2:
+ return paravirt_read_slot2(bundle);
+ default:
+ BUG();
+ }
+ /* NOTREACHED */
+}
+
+void __init_or_module
+paravirt_write_slot0(bundle_t *bundle, cmp_inst_t inst)
+{
+ bundle->quad0.slot0 = inst.l;
+}
+
+void __init_or_module
+paravirt_write_slot1(bundle_t *bundle, cmp_inst_t inst)
+{
+ bundle->quad0.slot1_p0 = inst.l;
+ bundle->quad1.slot1_p1 = inst.l >> 18UL;
+}
+
+void __init_or_module
+paravirt_write_slot2(bundle_t *bundle, cmp_inst_t inst)
+{
+ bundle->quad1.slot2 = inst.l;
+}
+
+void __init_or_module
+paravirt_write_inst(unsigned long tag, cmp_inst_t inst)
+{
+ bundle_t *bundle = paravirt_get_bundle(tag);
+ unsigned long slot = paravirt_get_slot(tag);
+
+ switch (slot) {
+ case 0:
+ paravirt_write_slot0(bundle, inst);
+ break;
+ case 1:
+ paravirt_write_slot1(bundle, inst);
+ break;
+ case 2:
+ paravirt_write_slot2(bundle, inst);
+ break;
+ default:
+ BUG();
+ }
+ paravirt_flush_i_cache_range(bundle, sizeof(*bundle));
+}
+
+/* for debug */
+void
+print_bundle(const bundle_t *bundle)
+{
+ const unsigned long *quad = (const unsigned long *)bundle;
+ cmp_inst_t slot0 = paravirt_read_slot0(bundle);
+ cmp_inst_t slot1 = paravirt_read_slot1(bundle);
+ cmp_inst_t slot2 = paravirt_read_slot2(bundle);
+
+ printk(KERN_DEBUG
+ "bundle 0x%p 0x%016lx 0x%016lx\n", bundle, quad[0], quad[1]);
+ printk(KERN_DEBUG
+ "bundle template 0x%x\n",
+ bundle->quad0.template);
+ printk(KERN_DEBUG
+ "slot0 0x%lx slot1_p0 0x%lx slot1_p1 0x%lx slot2 0x%lx\n",
+ (unsigned long)bundle->quad0.slot0,
+ (unsigned long)bundle->quad0.slot1_p0,
+ (unsigned long)bundle->quad1.slot1_p1,
+ (unsigned long)bundle->quad1.slot2);
+ printk(KERN_DEBUG
+ "slot0 0x%016llx slot1 0x%016llx slot2 0x%016llx\n",
+ slot0.l, slot1.l, slot2.l);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/arch/ia64/kernel/paravirt_entry.c b/arch/ia64/kernel/paravirt_entry.c
new file mode 100644
index 0000000..708287a
--- /dev/null
+++ b/arch/ia64/kernel/paravirt_entry.c
@@ -0,0 +1,99 @@
+/******************************************************************************
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/paravirt_core.h>
+#include <asm/paravirt_entry.h>
+
+/* br.cond.sptk.many <target25> B1 */
+typedef union inst_b1 {
+ cmp_inst_t inst;
+ struct {
+ unsigned long qp: 6;
+ unsigned long btype: 3;
+ unsigned long unused: 3;
+ unsigned long p: 1;
+ unsigned long imm20b: 20;
+ unsigned long wh: 2;
+ unsigned long d: 1;
+ unsigned long s: 1;
+ unsigned long opcode: 4;
+ };
+ unsigned long l;
+} inst_b1_t;
+
+static void __init
+__paravirt_entry_apply(unsigned long tag, const void *target)
+{
+ bundle_t *bundle = paravirt_get_bundle(tag);
+ cmp_inst_t inst = paravirt_read_inst(tag);
+ unsigned long target25 = (unsigned long)target - (unsigned long)bundle;
+ inst_b1_t inst_b1;
+
+ inst_b1.l = inst.l;
+ if (target25 & (1UL << 63))
+ inst_b1.s = 1;
+ else
+ inst_b1.s = 0;
+
+ inst_b1.imm20b = target25 >> 4;
+ inst.l = inst_b1.l;
+
+ paravirt_write_inst(tag, inst);
+ paravirt_flush_i_cache_range(bundle, sizeof(*bundle));
+}
+
+static void __init
+paravirt_entry_apply(const struct paravirt_entry_patch *entry_patch,
+ const struct paravirt_entry *entries,
+ unsigned int nr_entries)
+{
+ unsigned int i;
+ for (i = 0; i < nr_entries; i++) {
+ if (entry_patch->type == entries[i].type) {
+ __paravirt_entry_apply(entry_patch->tag,
+ entries[i].entry);
+ break;
+ }
+ }
+}
+
+void __init
+paravirt_entry_patch_apply(const struct paravirt_entry_patch *start,
+ const struct paravirt_entry_patch *end,
+ const struct paravirt_entry *entries,
+ unsigned int nr_entries)
+{
+ const struct paravirt_entry_patch *p;
+ for (p = start; p < end; p++)
+ paravirt_entry_apply(p, entries, nr_entries);
+
+ ia64_sync_i();
+ ia64_srlz_i();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/arch/ia64/kernel/paravirt_nop.c b/arch/ia64/kernel/paravirt_nop.c
new file mode 100644
index 0000000..ee5a204
--- /dev/null
+++ b/arch/ia64/kernel/paravirt_nop.c
@@ -0,0 +1,49 @@
+/******************************************************************************
+ * linux/arch/ia64/xen/paravirt_nop.c
+ *
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/paravirt_core.h>
+#include <asm/paravirt_nop.h>
+
+void __init_or_module
+paravirt_nop_b_patch_apply(const struct paravirt_nop_patch *start,
+ const struct paravirt_nop_patch *end)
+{
+ extern const bundle_t nop_b_inst_bundle;
+ const cmp_inst_t nop_b_inst = paravirt_read_slot0(&nop_b_inst_bundle);
+ const struct paravirt_nop_patch *p;
+
+ for (p = start; p < end; p++)
+ paravirt_write_inst(p->tag, nop_b_inst);
+
+ ia64_sync_i();
+ ia64_srlz_i();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 80622ac..0cbe0a1 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -163,6 +163,41 @@ SECTIONS
__end___mckinley_e9_bundles = .;
}
+#if defined(CONFIG_PARAVIRT_ALT)
+ . = ALIGN(16);
+ .paravirt_bundles : AT(ADDR(.paravirt_bundles) - LOAD_OFFSET)
+ {
+ __start_paravirt_bundles = .;
+ *(.paravirt_bundles)
+ __stop_paravirt_bundles = .;
+ }
+ . = ALIGN(16);
+ .paravirt_insts : AT(ADDR(.paravirt_insts) - LOAD_OFFSET)
+ {
+ __start_paravirt_insts = .;
+ *(.paravirt_insts)
+ __stop_paravirt_insts = .;
+ }
+#endif
+#if defined(CONFIG_PARAVIRT_NOP_B_PATCH)
+ . = ALIGN(16);
+ .paravirt_nop_b : AT(ADDR(.paravirt_nop_b) - LOAD_OFFSET)
+ {
+ __start_paravirt_nop_b = .;
+ *(.paravirt_nop_b)
+ __stop_paravirt_nop_b = .;
+ }
+#endif
+#if defined(CONFIG_PARAVIRT_ENTRY)
+ . = ALIGN(16);
+ .paravirt_entry : AT(ADDR(.paravirt_entry) - LOAD_OFFSET)
+ {
+ __start_paravirt_entry = .;
+ *(.paravirt_entry)
+ __stop_paravirt_entry = .;
+ }
+#endif
+
#if defined(CONFIG_IA64_GENERIC)
/* Machine Vector */
. = ALIGN(16);
diff --git a/include/asm-ia64/module.h b/include/asm-ia64/module.h
index d2da61e..44f63ff 100644
--- a/include/asm-ia64/module.h
+++ b/include/asm-ia64/module.h
@@ -16,6 +16,12 @@ struct mod_arch_specific {
struct elf64_shdr *got; /* global offset table */
struct elf64_shdr *opd; /* official procedure descriptors */
struct elf64_shdr *unwind; /* unwind-table section */
+#ifdef CONFIG_PARAVIRT_ALT
+ struct elf64_shdr *paravirt_bundles;
+ /* paravirt_alt_bundle_patch table */
+ struct elf64_shdr *paravirt_insts;
+ /* paravirt_alt_inst_patch table */
+#endif
unsigned long gp; /* global-pointer for module */
void *core_unw_table; /* core unwind-table cookie returned by unwinder */
diff --git a/include/asm-ia64/paravirt_alt.h b/include/asm-ia64/paravirt_alt.h
new file mode 100644
index 0000000..34c5473
--- /dev/null
+++ b/include/asm-ia64/paravirt_alt.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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_PARAVIRT_ALT_H
+#define __ASM_PARAVIRT_ALT_H
+
+#ifndef __ASSEMBLER__
+/* for binary patch */
+struct paravirt_alt_bundle_patch {
+ void *sbundle;
+ void *ebundle;
+ unsigned long type;
+};
+
+/* label means the beginning of new bundle */
+#define paravirt_alt_bundle(instr, privop) \
+ "\t1:\n" \
+ "\t" instr "\n" \
+ "\t2:\n" \
+ "\t.section .paravirt_bundles, \"a\"\n" \
+ "\t.previous\n" \
+ "\t.xdata8 \".paravirt_bundles\", 1b, 2b, " \
+ __stringify(privop) "\n"
+
+struct paravirt_alt_inst_patch {
+ unsigned long stag;
+ unsigned long etag;
+ unsigned long type;
+};
+
+#define paravirt_alt_inst(instr, privop) \
+ "\t[1:]\n" \
+ "\t" instr "\n" \
+ "\t[2:]\n" \
+ "\t.section .paravirt_insts, \"a\"\n" \
+ "\t.previous\n" \
+ "\t.xdata8 \".paravirt_insts\", 1b, 2b, " \
+ __stringify(privop) "\n"
+
+void
+paravirt_alt_bundle_patch_apply(struct paravirt_alt_bundle_patch *start,
+ struct paravirt_alt_bundle_patch *end,
+ unsigned long(*patch)(void *sbundle,
+ void *ebundle,
+ unsigned long type));
+
+void
+paravirt_alt_inst_patch_apply(struct paravirt_alt_inst_patch *start,
+ struct paravirt_alt_inst_patch *end,
+ unsigned long (*patch)(unsigned long stag,
+ unsigned long etag,
+ unsigned long type));
+#endif /* __ASSEMBLER__ */
+
+#endif /* __ASM_PARAVIRT_ALT_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/include/asm-ia64/paravirt_core.h b/include/asm-ia64/paravirt_core.h
new file mode 100644
index 0000000..9979740
--- /dev/null
+++ b/include/asm-ia64/paravirt_core.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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_PARAVIRT_CORE_H
+#define __ASM_PARAVIRT_CORE_H
+
+#include <asm/kprobes.h>
+
+void paravirt_flush_i_cache_range(const void *instr, unsigned long size);
+
+bundle_t *paravirt_get_bundle(unsigned long tag);
+unsigned long paravirt_get_slot(unsigned long tag);
+unsigned long paravirt_get_next_tag(unsigned long tag);
+
+cmp_inst_t paravirt_read_slot0(const bundle_t *bundle);
+cmp_inst_t paravirt_read_slot1(const bundle_t *bundle);
+cmp_inst_t paravirt_read_slot2(const bundle_t *bundle);
+cmp_inst_t paravirt_read_inst(unsigned long tag);
+
+void paravirt_write_slot0(bundle_t *bundle, cmp_inst_t inst);
+void paravirt_write_slot1(bundle_t *bundle, cmp_inst_t inst);
+void paravirt_write_slot2(bundle_t *bundle, cmp_inst_t inst);
+void paravirt_write_inst(unsigned long tag, cmp_inst_t inst);
+
+void print_bundle(const bundle_t *bundle);
+
+#endif /* __ASM_PARAVIRT_CORE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/include/asm-ia64/paravirt_entry.h b/include/asm-ia64/paravirt_entry.h
new file mode 100644
index 0000000..857fd37
--- /dev/null
+++ b/include/asm-ia64/paravirt_entry.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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_PARAVIRT_ENTRY_H
+#define __ASM_PARAVIRT_ENTRY_H
+
+#ifdef __ASSEMBLY__
+
+#define BR_COND_SPTK_MANY(target, type) \
+ [1:] ; \
+ br.cond.sptk.many target;; ; \
+ .section .paravirt_entry, "a" ; \
+ .previous ; \
+ .xdata8 ".paravirt_entry", 1b, type
+
+#else /* __ASSEMBLY__ */
+
+struct paravirt_entry_patch {
+ unsigned long tag;
+ unsigned long type;
+};
+
+struct paravirt_entry {
+ void *entry;
+ unsigned long type;
+};
+
+void
+paravirt_entry_patch_apply(const struct paravirt_entry_patch *start,
+ const struct paravirt_entry_patch *end,
+ const struct paravirt_entry *entries,
+ unsigned int nr_entries);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_PARAVIRT_ENTRY_H */
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/include/asm-ia64/paravirt_nop.h b/include/asm-ia64/paravirt_nop.h
new file mode 100644
index 0000000..2b05430
--- /dev/null
+++ b/include/asm-ia64/paravirt_nop.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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_PARAVIRT_OPS_H
+#define __ASM_PARAVIRT_OPS_H
+
+#ifndef __ASSEMBLY__
+
+struct paravirt_nop_patch {
+ unsigned long tag;
+};
+
+void
+paravirt_nop_b_patch_apply(const struct paravirt_nop_patch *start,
+ const struct paravirt_nop_patch *end);
+
+#endif /* !__ASSEMBLEY__ */
+
+#endif /* __ASM_PARAVIRT_OPS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 12/28] RFC: ia64/xen: xen privileged instruction intrinsics binary patching.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (10 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 11/28] ia64: introduce basic facilities for binary patching yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU yamahata
` (20 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0012-ia64-xen-xen-privileged-instruction-intrinsics-bina.patch --]
[-- Type: text/plain, Size: 49318 bytes --]
With binary patching, make intrinsics paravirtualization hypervisor neutral.
So far xen intrinsics doesn't allow another hypervisor.
Mark privileged operations which needs paravirtualization and binary patch
if running on xen at early boot time.
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/module.c | 32 ++
arch/ia64/kernel/paravirtentry.S | 37 +++
arch/ia64/xen/Makefile | 7 +
arch/ia64/xen/paravirt_xen.c | 242 +++++++++++++++
arch/ia64/xen/privops_asm.S | 221 ++++++++++++++
arch/ia64/xen/privops_c.c | 279 +++++++++++++++++
arch/ia64/xen/xensetup.S | 10 +
include/asm-ia64/privop.h | 4 +
include/asm-ia64/privop_paravirt.h | 587 ++++++++++++++++++++++++++++++++++++
include/asm-ia64/xen/privop.h | 24 ++
10 files changed, 1443 insertions(+), 0 deletions(-)
create mode 100644 arch/ia64/kernel/paravirtentry.S
create mode 100644 arch/ia64/xen/Makefile
create mode 100644 arch/ia64/xen/paravirt_xen.c
create mode 100644 arch/ia64/xen/privops_asm.S
create mode 100644 arch/ia64/xen/privops_c.c
create mode 100644 include/asm-ia64/privop_paravirt.h
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index e58f436..2806f70 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -454,6 +454,14 @@ module_frob_arch_sections (Elf_Ehdr *ehdr, Elf_Shdr *sechdrs, char *secstrings,
mod->arch.opd = s;
else if (strcmp(".IA_64.unwind", secstrings + s->sh_name) == 0)
mod->arch.unwind = s;
+#ifdef CONFIG_PARAVIRT_ALT
+ else if (strcmp(".paravirt_bundles",
+ secstrings + s->sh_name) == 0)
+ mod->arch.paravirt_bundles = s;
+ else if (strcmp(".paravirt_insts",
+ secstrings + s->sh_name) == 0)
+ mod->arch.paravirt_insts = s;
+#endif
if (!mod->arch.core_plt || !mod->arch.init_plt || !mod->arch.got || !mod->arch.opd) {
printk(KERN_ERR "%s: sections missing\n", mod->name);
@@ -929,6 +937,30 @@ module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mo
DEBUGP("%s: init: entry=%p\n", __FUNCTION__, mod->init);
if (mod->arch.unwind)
register_unwind_table(mod);
+#ifdef CONFIG_PARAVIRT_ALT
+ if (mod->arch.paravirt_bundles) {
+ struct paravirt_alt_bundle_patch *start =
+ (struct paravirt_alt_bundle_patch *)
+ mod->arch.paravirt_bundles->sh_addr;
+ struct paravirt_alt_bundle_patch *end =
+ (struct paravirt_alt_bundle_patch *)
+ (mod->arch.paravirt_bundles->sh_addr +
+ mod->arch.paravirt_bundles->sh_size);
+
+ xen_alt_bundle_patch_module(start, end);
+ }
+ if (mod->arch.paravirt_insts) {
+ struct paravirt_alt_inst_patch *start =
+ (struct paravirt_alt_inst_patch *)
+ mod->arch.paravirt_insts->sh_addr;
+ struct paravirt_alt_inst_patch *end =
+ (struct paravirt_alt_inst_patch *)
+ (mod->arch.paravirt_insts->sh_addr +
+ mod->arch.paravirt_insts->sh_size);
+
+ xen_alt_inst_patch_module(start, end);
+ }
+#endif
return 0;
}
diff --git a/arch/ia64/kernel/paravirtentry.S b/arch/ia64/kernel/paravirtentry.S
new file mode 100644
index 0000000..99606d0
--- /dev/null
+++ b/arch/ia64/kernel/paravirtentry.S
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * linux/arch/ia64/xen/paravirtentry.S
+ *
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 <asm/asmmacro.h>
+#include <asm/paravirt_entry.h>
+#include <asm/privop_paravirt.h>
+
+#define BRANCH(sym, type) \
+ GLOBAL_ENTRY(paravirt_ ## sym) ; \
+ BR_COND_SPTK_MANY(__ia64_ ## sym, type) ; \
+ END(paravirt_ ## sym)
+
+ BRANCH(switch_to, PARAVIRT_ENTRY_SWITCH_TO)
+ BRANCH(leave_syscall, PARAVIRT_ENTRY_LEAVE_SYSCALL)
+ BRANCH(work_processed_syscall, PARAVIRT_ENTRY_WORK_PROCESSED_SYSCALL)
+ BRANCH(leave_kernel, PARAVIRT_ENTRY_LEAVE_KERNEL)
+ BRANCH(pal_call_static, PARAVIRT_ENTRY_PAL_CALL_STATIC)
diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile
new file mode 100644
index 0000000..c219358
--- /dev/null
+++ b/arch/ia64/xen/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Xen components
+#
+
+obj-$(CONFIG_PARAVIRT_ALT) += paravirt_xen.o privops_asm.o privops_c.o
+obj-$(CONFIG_PARAVIRT_NOP_B_PATCH) += paravirt_xen.o
+obj-$(CONFIG_PARAVIRT_ENTRY) += paravirt_xen.o
diff --git a/arch/ia64/xen/paravirt_xen.c b/arch/ia64/xen/paravirt_xen.c
new file mode 100644
index 0000000..57b9dfd
--- /dev/null
+++ b/arch/ia64/xen/paravirt_xen.c
@@ -0,0 +1,242 @@
+/******************************************************************************
+ * linux/arch/ia64/xen/paravirt_xen.c
+ *
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/types.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <asm/intrinsics.h>
+#include <asm/bugs.h>
+#include <asm/kprobes.h> /* for bundle_t */
+#include <asm/paravirt_core.h>
+
+#ifdef CONFIG_PARAVIRT_ALT
+struct xen_alt_bundle_patch_elem {
+ const void *sbundle;
+ const void *ebundle;
+ unsigned long type;
+};
+
+static unsigned long __init_or_module
+__xen_alt_bundle_patch(void *sbundle, void *ebundle, unsigned long type)
+{
+ extern const struct xen_alt_bundle_patch_elem xen_alt_bundle_array[];
+ extern const unsigned long xen_alt_bundle_array_size;
+
+ unsigned long used = 0;
+ unsigned long i;
+
+ BUG_ON((((unsigned long)sbundle) % sizeof(bundle_t)) != 0);
+ BUG_ON((((unsigned long)ebundle) % sizeof(bundle_t)) != 0);
+
+ for (i = 0;
+ i < xen_alt_bundle_array_size / sizeof(xen_alt_bundle_array[0]);
+ i++) {
+ const struct xen_alt_bundle_patch_elem *p =
+ &xen_alt_bundle_array[i];
+ if (p->type == type) {
+ used = p->ebundle - p->sbundle;
+ BUG_ON(used > ebundle - sbundle);
+ memcpy(sbundle, p->sbundle, used);
+ break;
+ }
+ }
+
+ return used;
+}
+
+static void __init
+xen_alt_bundle_patch(void)
+{
+ extern struct paravirt_alt_bundle_patch __start_paravirt_bundles[];
+ extern struct paravirt_alt_bundle_patch __stop_paravirt_bundles[];
+
+ paravirt_alt_bundle_patch_apply(__start_paravirt_bundles,
+ __stop_paravirt_bundles,
+ &__xen_alt_bundle_patch);
+}
+
+#ifdef CONFIG_MODULES
+void
+xen_alt_bundle_patch_module(struct paravirt_alt_bundle_patch *start,
+ struct paravirt_alt_bundle_patch *end)
+{
+ if (is_running_on_xen())
+ paravirt_alt_bundle_patch_apply(start, end,
+ &__xen_alt_bundle_patch);
+}
+#endif /* CONFIG_MODULES */
+
+
+/*
+ * all the native instructions of hyperprivops are M-form or I-form
+ * mov ar.<imm>=r1 I26, M29
+ * mov r1=ar.<imm> I28, M31
+ * mov r1=cr.<imm> M32
+ * mov cr.<imm>=r1 M33
+ * mov r1=psr M36
+ * mov indirect<r1>=r2 M42
+ * mov r1=indirect<r2> M43
+ * ptc.ga M45
+ * thash r1=r2 M46
+ *
+ * break.{m, i} instrucitions format are same.
+ * So we can safely replace all signle instruction which is target of
+ * hyperpviops with break.{m, i} imm21 hyperprivops.
+ */
+
+struct xen_alt_inst_patch_elem {
+ unsigned long stag;
+ unsigned long etag;
+ unsigned long type;
+};
+
+unsigned long
+__xen_alt_inst_patch(unsigned long stag, unsigned long etag,
+ unsigned long type)
+{
+ extern const struct xen_alt_inst_patch_elem xen_alt_inst_array[];
+ extern const unsigned long xen_alt_inst_array_size;
+
+ unsigned long dest_tag = stag;
+ unsigned long i;
+
+ for (i = 0;
+ i < xen_alt_inst_array_size / sizeof(xen_alt_inst_array[0]);
+ i++) {
+ const struct xen_alt_inst_patch_elem *p =
+ &xen_alt_inst_array[i];
+ if (p->type == type) {
+ unsigned long src_tag;
+
+ for (src_tag = p->stag;
+ src_tag < p->etag;
+ src_tag = paravirt_get_next_tag(src_tag)) {
+ const cmp_inst_t inst =
+ paravirt_read_inst(src_tag);
+ paravirt_write_inst(dest_tag, inst);
+
+ BUG_ON(dest_tag >= etag);
+ dest_tag = paravirt_get_next_tag(dest_tag);
+ }
+ break;
+ }
+ }
+
+ return dest_tag;
+}
+
+void
+xen_alt_inst_patch(void)
+{
+ extern struct paravirt_alt_inst_patch __start_paravirt_insts[];
+ extern struct paravirt_alt_inst_patch __stop_paravirt_insts[];
+
+ paravirt_alt_inst_patch_apply(__start_paravirt_insts,
+ __stop_paravirt_insts,
+ &__xen_alt_inst_patch);
+}
+
+#ifdef CONFIG_MODULES
+void
+xen_alt_inst_patch_module(struct paravirt_alt_inst_patch *start,
+ struct paravirt_alt_inst_patch *end)
+{
+ if (is_running_on_xen())
+ paravirt_alt_inst_patch_apply(start, end,
+ &__xen_alt_inst_patch);
+}
+#endif
+
+#else
+#define xen_alt_bundle_patch() do { } while (0)
+#define xen_alt_inst_patch() do { } while (0)
+#endif /* CONFIG_PARAVIRT_ALT */
+
+
+#ifdef CONFIG_PARAVIRT_NOP_B_PATCH
+#include <asm/paravirt_nop.h>
+static void __init
+xen_nop_b_patch(void)
+{
+ extern const struct paravirt_nop_patch __start_paravirt_nop_b[];
+ extern const struct paravirt_nop_patch __stop_paravirt_nop_b[];
+
+ paravirt_nop_b_patch_apply(__start_paravirt_nop_b,
+ __stop_paravirt_nop_b);
+}
+#else
+#define xen_nop_b_patch() do { } while (0)
+#endif
+
+
+#ifdef CONFIG_PARAVIRT_ENTRY
+
+#include <asm/paravirt_entry.h>
+
+extern void *xen_switch_to;
+extern void *xen_leave_syscall;
+extern void *xen_leave_kernel;
+extern void *xen_pal_call_static;
+extern void *xen_work_processed_syscall;
+
+const static struct paravirt_entry xen_entries[] __initdata = {
+ {&xen_switch_to, PARAVIRT_ENTRY_SWITCH_TO},
+ {&xen_leave_syscall, PARAVIRT_ENTRY_LEAVE_SYSCALL},
+ {&xen_leave_kernel, PARAVIRT_ENTRY_LEAVE_KERNEL},
+ {&xen_pal_call_static, PARAVIRT_ENTRY_PAL_CALL_STATIC},
+ {&xen_work_processed_syscall, PARAVIRT_ENTRY_WORK_PROCESSED_SYSCALL},
+};
+
+void __init
+xen_entry_patch(void)
+{
+ extern const struct paravirt_entry_patch __start_paravirt_entry[];
+ extern const struct paravirt_entry_patch __stop_paravirt_entry[];
+
+ paravirt_entry_patch_apply(__start_paravirt_entry,
+ __stop_paravirt_entry,
+ xen_entries,
+ sizeof(xen_entries)/sizeof(xen_entries[0]));
+}
+#else
+#define xen_entry_patch() do { } while (0)
+#endif
+
+
+void __init
+xen_paravirt_patch(void)
+{
+ xen_alt_bundle_patch();
+ xen_alt_inst_patch();
+ xen_nop_b_patch();
+ xen_entry_patch();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "linux"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/arch/ia64/xen/privops_asm.S b/arch/ia64/xen/privops_asm.S
new file mode 100644
index 0000000..40e400e
--- /dev/null
+++ b/arch/ia64/xen/privops_asm.S
@@ -0,0 +1,221 @@
+/******************************************************************************
+ * linux/arch/ia64/xen/privop_s.S
+ *
+ * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/intrinsics.h>
+#include <linux/init.h>
+#include <asm/paravirt_alt.h>
+
+#ifdef CONFIG_MODULES
+#define __INIT_OR_MODULE .text
+#define __INITDATA_OR_MODULE .data
+#else
+#define __INIT_OR_MODULE __INIT
+#define __INITDATA_OR_MODULE __INITDATA
+#endif /* CONFIG_MODULES */
+
+ __INIT_OR_MODULE
+ .align 32
+ .proc nop_b_inst_bundle
+ .global nop_b_inst_bundle
+nop_b_inst_bundle:
+ {
+ nop.b 0
+ nop.b 0
+ nop.b 0
+ }
+ .endp nop_b_inst_bundle
+ __FINIT
+
+ /* NOTE: nop.[mfi] has same format */
+ __INIT_OR_MODULE
+ .align 32
+ .proc nop_mfi_inst_bundle
+ .global nop_mfi_inst_bundle
+nop_mfi_inst_bundle:
+ {
+ nop.m 0
+ nop.f 0
+ nop.i 0
+ }
+ .endp nop_mfi_inst_bundle
+ __FINIT
+
+ __INIT_OR_MODULE
+ .align 32
+ .proc nop_bundle
+ .global nop_bundle
+nop_bundle:
+nop_bundle_start:
+ {
+ nop 0
+ nop 0
+ nop 0
+ }
+nop_bundle_end:
+ .endp nop_bundle
+ __FINIT
+
+ __INITDATA_OR_MODULE
+ .align 8
+ .global nop_bundle_size
+nop_bundle_size:
+ data8 nop_bundle_end - nop_bundle_start
+
+#define DEFINE_PRIVOP(name, instr) \
+ .align 32; \
+ .proc xen_ ## name ## _instr; \
+ xen_ ## name ## _instr:; \
+ xen_ ## name ## _instr_start:; \
+ {; \
+ [xen_ ## name ## _stag:] \
+ instr; \
+ [xen_ ## name ## _etag:] \
+ nop 0; \
+ nop 0; \
+ }; \
+ xen_ ## name ## _instr_end:; \
+ .endp xen_ ## name ## _instr;
+
+ __INIT_OR_MODULE
+ DEFINE_PRIVOP(rfi, XEN_HYPER_RFI)
+ DEFINE_PRIVOP(rsm_psr_dt, XEN_HYPER_RSM_PSR_DT)
+ DEFINE_PRIVOP(ssm_psr_dt, XEN_HYPER_SSM_PSR_DT)
+ DEFINE_PRIVOP(cover, XEN_HYPER_COVER)
+ DEFINE_PRIVOP(itc_d, XEN_HYPER_ITC_D)
+ DEFINE_PRIVOP(itc_i, XEN_HYPER_ITC_I)
+ DEFINE_PRIVOP(ssm_i, XEN_HYPER_SSM_I)
+ DEFINE_PRIVOP(get_ivr, XEN_HYPER_GET_IVR)
+ DEFINE_PRIVOP(get_tpr, XEN_HYPER_GET_TPR)
+ DEFINE_PRIVOP(set_tpr, XEN_HYPER_SET_TPR)
+ DEFINE_PRIVOP(eoi, XEN_HYPER_EOI)
+ DEFINE_PRIVOP(set_itm, XEN_HYPER_SET_ITM)
+ DEFINE_PRIVOP(thash, XEN_HYPER_THASH)
+ DEFINE_PRIVOP(ptc_ga, XEN_HYPER_PTC_GA)
+ DEFINE_PRIVOP(itr_d, XEN_HYPER_ITR_D)
+ DEFINE_PRIVOP(get_rr, XEN_HYPER_GET_RR)
+ DEFINE_PRIVOP(set_rr, XEN_HYPER_SET_RR)
+ DEFINE_PRIVOP(set_kr, XEN_HYPER_SET_KR)
+ DEFINE_PRIVOP(fc, XEN_HYPER_FC)
+ DEFINE_PRIVOP(get_cpuid, XEN_HYPER_GET_CPUID)
+ DEFINE_PRIVOP(get_pmd, XEN_HYPER_GET_PMD)
+ DEFINE_PRIVOP(get_eflag, XEN_HYPER_GET_EFLAG)
+ DEFINE_PRIVOP(set_eflag, XEN_HYPER_SET_EFLAG)
+ DEFINE_PRIVOP(get_psr, XEN_HYPER_GET_PSR)
+ DEFINE_PRIVOP(set_rr0_to_rr4, XEN_HYPER_SET_RR0_TO_RR4)
+ __FINIT
+
+
+#define PARAVIRT_ALT_BUNDLE_ELEM(name, type) \
+ data8 xen_ ## name ## _instr_start; \
+ data8 xen_ ## name ## _instr_end; \
+ data8 type;
+
+ __INITDATA_OR_MODULE
+ .align 8
+ .global xen_alt_bundle_array
+xen_alt_bundle_array:
+xen_alt_bundle_array_start:
+ PARAVIRT_ALT_BUNDLE_ELEM(rfi, PARAVIRT_INST_RFI)
+ PARAVIRT_ALT_BUNDLE_ELEM(rsm_psr_dt, PARAVIRT_INST_RSM_DT)
+ PARAVIRT_ALT_BUNDLE_ELEM(ssm_psr_dt, PARAVIRT_INST_SSM_DT)
+ PARAVIRT_ALT_BUNDLE_ELEM(cover, PARAVIRT_INST_COVER)
+ PARAVIRT_ALT_BUNDLE_ELEM(itc_d, PARAVIRT_INST_ITC_D)
+ PARAVIRT_ALT_BUNDLE_ELEM(itc_i, PARAVIRT_INST_ITC_I)
+ PARAVIRT_ALT_BUNDLE_ELEM(ssm_i, PARAVIRT_INST_SSM_I)
+ PARAVIRT_ALT_BUNDLE_ELEM(get_ivr, PARAVIRT_INST_GET_IVR)
+ PARAVIRT_ALT_BUNDLE_ELEM(get_tpr, PARAVIRT_INST_GET_TPR)
+ PARAVIRT_ALT_BUNDLE_ELEM(set_tpr, PARAVIRT_INST_SET_TPR)
+ PARAVIRT_ALT_BUNDLE_ELEM(eoi, PARAVIRT_INST_EOI)
+ PARAVIRT_ALT_BUNDLE_ELEM(set_itm, PARAVIRT_INST_SET_ITM)
+ PARAVIRT_ALT_BUNDLE_ELEM(thash, PARAVIRT_INST_THASH)
+ PARAVIRT_ALT_BUNDLE_ELEM(ptc_ga, PARAVIRT_INST_PTC_GA)
+ PARAVIRT_ALT_BUNDLE_ELEM(itr_d, PARAVIRT_INST_ITR_D)
+ PARAVIRT_ALT_BUNDLE_ELEM(get_rr, PARAVIRT_INST_GET_RR)
+ PARAVIRT_ALT_BUNDLE_ELEM(set_rr, PARAVIRT_INST_SET_RR)
+ PARAVIRT_ALT_BUNDLE_ELEM(set_kr, PARAVIRT_INST_SET_KR)
+ PARAVIRT_ALT_BUNDLE_ELEM(fc, PARAVIRT_INST_FC)
+ PARAVIRT_ALT_BUNDLE_ELEM(get_cpuid, PARAVIRT_INST_GET_CPUID)
+ PARAVIRT_ALT_BUNDLE_ELEM(get_pmd, PARAVIRT_INST_GET_PMD)
+ PARAVIRT_ALT_BUNDLE_ELEM(get_eflag, PARAVIRT_INST_GET_EFLAG)
+ PARAVIRT_ALT_BUNDLE_ELEM(set_eflag, PARAVIRT_INST_SET_EFLAG)
+ PARAVIRT_ALT_BUNDLE_ELEM(get_psr, PARAVIRT_INST_GET_PSR)
+
+ PARAVIRT_ALT_BUNDLE_ELEM(ssm_i, PARAVIRT_BNDL_SSM_I)
+ PARAVIRT_ALT_BUNDLE_ELEM(rsm_i, PARAVIRT_BNDL_RSM_I)
+ PARAVIRT_ALT_BUNDLE_ELEM(get_psr_i, PARAVIRT_BNDL_GET_PSR_I)
+ PARAVIRT_ALT_BUNDLE_ELEM(intrin_local_irq_restore,
+ PARAVIRT_BNDL_INTRIN_LOCAL_IRQ_RESTORE)
+xen_alt_bundle_array_end:
+
+ .align 8
+ .global xen_alt_bundle_array_size
+xen_alt_bundle_array_size:
+ .long xen_alt_bundle_array_end - xen_alt_bundle_array_start
+
+
+#define PARAVIRT_ALT_INST_ELEM(name, type) \
+ data8 xen_ ## name ## _stag ; \
+ data8 xen_ ## name ## _etag ; \
+ data8 type
+
+ __INITDATA_OR_MODULE
+ .align 8
+ .global xen_alt_inst_array
+xen_alt_inst_array:
+xen_alt_inst_array_start:
+ PARAVIRT_ALT_INST_ELEM(rfi, PARAVIRT_INST_RFI)
+ PARAVIRT_ALT_INST_ELEM(rsm_psr_dt, PARAVIRT_INST_RSM_DT)
+ PARAVIRT_ALT_INST_ELEM(ssm_psr_dt, PARAVIRT_INST_SSM_DT)
+ PARAVIRT_ALT_INST_ELEM(cover, PARAVIRT_INST_COVER)
+ PARAVIRT_ALT_INST_ELEM(itc_d, PARAVIRT_INST_ITC_D)
+ PARAVIRT_ALT_INST_ELEM(itc_i, PARAVIRT_INST_ITC_I)
+ PARAVIRT_ALT_INST_ELEM(ssm_i, PARAVIRT_INST_SSM_I)
+ PARAVIRT_ALT_INST_ELEM(get_ivr, PARAVIRT_INST_GET_IVR)
+ PARAVIRT_ALT_INST_ELEM(get_tpr, PARAVIRT_INST_GET_TPR)
+ PARAVIRT_ALT_INST_ELEM(set_tpr, PARAVIRT_INST_SET_TPR)
+ PARAVIRT_ALT_INST_ELEM(eoi, PARAVIRT_INST_EOI)
+ PARAVIRT_ALT_INST_ELEM(set_itm, PARAVIRT_INST_SET_ITM)
+ PARAVIRT_ALT_INST_ELEM(thash, PARAVIRT_INST_THASH)
+ PARAVIRT_ALT_INST_ELEM(ptc_ga, PARAVIRT_INST_PTC_GA)
+ PARAVIRT_ALT_INST_ELEM(itr_d, PARAVIRT_INST_ITR_D)
+ PARAVIRT_ALT_INST_ELEM(get_rr, PARAVIRT_INST_GET_RR)
+ PARAVIRT_ALT_INST_ELEM(set_rr, PARAVIRT_INST_SET_RR)
+ PARAVIRT_ALT_INST_ELEM(set_kr, PARAVIRT_INST_SET_KR)
+ PARAVIRT_ALT_INST_ELEM(fc, PARAVIRT_INST_FC)
+ PARAVIRT_ALT_INST_ELEM(get_cpuid, PARAVIRT_INST_GET_CPUID)
+ PARAVIRT_ALT_INST_ELEM(get_pmd, PARAVIRT_INST_GET_PMD)
+ PARAVIRT_ALT_INST_ELEM(get_eflag, PARAVIRT_INST_GET_EFLAG)
+ PARAVIRT_ALT_INST_ELEM(set_eflag, PARAVIRT_INST_SET_EFLAG)
+ PARAVIRT_ALT_INST_ELEM(get_psr, PARAVIRT_INST_GET_PSR)
+ PARAVIRT_ALT_INST_ELEM(set_rr0_to_rr4, PARAVIRT_INST_SET_RR0_TO_RR4)
+
+ PARAVIRT_ALT_INST_ELEM(ssm_i, PARAVIRT_BNDL_SSM_I)
+ PARAVIRT_ALT_INST_ELEM(rsm_i, PARAVIRT_BNDL_RSM_I)
+ PARAVIRT_ALT_INST_ELEM(get_psr_i, PARAVIRT_BNDL_GET_PSR_I)
+ PARAVIRT_ALT_INST_ELEM(intrin_local_irq_restore,
+ PARAVIRT_BNDL_INTRIN_LOCAL_IRQ_RESTORE)
+xen_alt_inst_array_end:
+
+ .align 8
+ .global xen_alt_inst_array_size
+xen_alt_inst_array_size:
+ .long xen_alt_inst_array_end - xen_alt_inst_array_start
diff --git a/arch/ia64/xen/privops_c.c b/arch/ia64/xen/privops_c.c
new file mode 100644
index 0000000..0fa2e23
--- /dev/null
+++ b/arch/ia64/xen/privops_c.c
@@ -0,0 +1,279 @@
+/******************************************************************************
+ * arch/ia64/xen/privops_c.c
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/linkage.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <xen/interface/xen.h>
+
+#include <asm/asm-offsets.h>
+#define XEN_PSR_I_ADDR_ADDR ((uint8_t **)(XSI_BASE + XSI_PSR_I_ADDR_OFS))
+
+
+void __init_or_module
+xen_privop_ssm_i(void)
+{
+ /*
+ * int masked = !xen_get_virtual_psr_i();
+ * // masked = *(*XEN_MAPPEDREGS->interrupt_mask_addr)
+ * xen_set_virtual_psr_i(1)
+ * // *(*XEN_MAPPEDREGS->interrupt_mask_addr) = 0
+ * // compiler barrier
+ * if (masked) {
+ * uint8_t* pend_int_addr =
+ * (uint8_t*)(*XEN_MAPPEDREGS->interrupt_mask_addr) - 1;
+ * uint8_t pending = *pend_int_addr;
+ * if (pending)
+ * XEN_HYPER_SSM_I
+ * }
+ */
+ register uint8_t *tmp asm ("r8");
+ register int masked asm ("r9");
+ register uint8_t *pending_intr_addr asm ("r10");
+
+ asm volatile(".global xen_ssm_i_instr\n\t"
+ "xen_ssm_i_instr:\n\t"
+ ".global xen_ssm_i_instr_start\n\t"
+ "xen_ssm_i_instr_start:\n\t"
+ ".global xen_ssm_i_stag\n\t"
+ "[xen_ssm_i_stag:]\n\t"
+ /* tmp = &XEN_MAPPEDREGS->interrupt_mask_addr */
+ "mov %[tmp]=%[XEN_PSR_I_ADDR_ADDR_IMM]\n\t"
+ ";;\n\t"
+ /* tmp = *XEN_MAPPEDREGS->interrupt_mask_addr */
+ "ld8 %[tmp]=[%[tmp]]\n\t"
+ ";;\n\t"
+ /* pending_intr_addr = tmp - 1 */
+ "add %[pending_intr_addr]=-1,%[tmp]\n\t"
+ /* masked = *tmp */
+ "ld1 %[masked]=[%[tmp]]\n\t"
+ ";;\n\t"
+ /* *tmp = 0 */
+ "st1 [%[tmp]]=r0\n\t"
+ /* p6 = !masked */
+ "cmp.ne.unc p6,p0=%[masked],r0\n\t"
+ ";;\n\t"
+ /* tmp = *pending_intr_addr */
+ "(p6) ld1 %[tmp]=[%[pending_intr_addr]]\n\t"
+ ";;\n\t"
+ /* p7 = p6 && !tmp */
+ "(p6) cmp.ne.unc p7,p0=%[tmp],r0\n\t"
+ ";;\n\t"
+ "(p7) break %[HYPERPRIVOP_SSM_I_IMM]\n\t"
+ ".global xen_ssm_i_etag\n\t"
+ "[xen_ssm_i_etag:]\n\t"
+ ".global xen_ssm_i_instr_end\n\t"
+ "xen_ssm_i_instr_end:\n\t"
+ :
+ [tmp] "=r"(tmp),
+ [pending_intr_addr] "=r"(pending_intr_addr),
+ [masked] "=r"(masked),
+
+ "=m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR))
+ :
+ [XEN_PSR_I_ADDR_ADDR_IMM] "i"(XEN_PSR_I_ADDR_ADDR),
+ [HYPERPRIVOP_SSM_I_IMM] "i"(HYPERPRIVOP_SSM_I),
+
+ "m"(*((uint8_t *)XEN_PSR_I_ADDR_ADDR)),
+ "m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)),
+ "m"(*(*((uint8_t **)XEN_PSR_I_ADDR_ADDR) - 1))
+ :
+ "memory",
+ /*
+ * predicate registers can't be specified as C variables
+ * so that we use p6, p7, p8 here.
+ */
+ "p6", /* is_old */
+ "p7" /* is_pending */
+ );
+}
+
+void __init_or_module
+xen_privop_rsm_i(void)
+{
+ /*
+ * psr_i_addr_addr = XEN_MAPPEDREGS->interrupt_mask_addr
+ * = XEN_PSR_I_ADDR_ADDR;
+ * psr_i_addr = *psr_i_addr_addr;
+ * *psr_i_addr = 1;
+ */
+ register unsigned long psr_i_addr asm("r8");
+ register uint8_t mask asm ("r9");
+ asm volatile (".global xen_rsm_i_instr\n\t"
+ "xen_rsm_i_instr:\n\t"
+ ".global xen_rsm_i_instr_start\n\t"
+ "xen_rsm_i_instr_start:\n\t"
+ ".global xen_rsm_i_stag\n\t"
+ "[xen_rsm_i_stag:]\n\t"
+ "mov %[psr_i_addr]=%[XEN_PSR_I_ADDR_ADDR_IMM]\n\t"
+ "mov %[mask]=%[ONE_IMM]\n\t"
+ ";;\n\t"
+ "ld8 %[psr_i_addr]=[%[psr_i_addr]]\n\t"
+ ";;\n\t"
+ "st1 [%[psr_i_addr]]=%[mask]\n\t"
+ ".global xen_rsm_i_etag\n\t"
+ "[xen_rsm_i_etag:]\n\t"
+ ".global xen_rsm_i_instr_end\n\t"
+ "xen_rsm_i_instr_end:\n\t"
+ :
+ [psr_i_addr] "=r"(psr_i_addr),
+ [mask] "=r"(mask),
+ "=m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)):
+ [XEN_PSR_I_ADDR_ADDR_IMM] "i"(XEN_PSR_I_ADDR_ADDR),
+ [ONE_IMM] "i"(1),
+ "m"(*((uint8_t **)XEN_PSR_I_ADDR_ADDR)):
+ "memory");
+}
+
+void __init_or_module
+xen_privop_ia64_intrin_local_irq_restore(unsigned long val)
+{
+ /*
+ * psr_i_addr_addr = XEN_PSR_I_ADDR_ADDR
+ * psr_i_addr = *psr_i_addr_addr
+ * pending_intr_addr = psr_i_addr - 1
+ * if (val & IA64_PSR_I) {
+ * masked = *psr_i_addr
+ * *psr_i_addr = 0
+ * compiler barrier
+ * if (masked) {
+ * uint8_t pending = *pending_intr_addr;
+ * if (pending)
+ * XEN_HYPER_SSM_I
+ * }
+ * } else {
+ * *psr_i_addr = 1
+ * }
+ */
+
+ register unsigned long __val asm("r8") = val;
+ register uint8_t *psr_i_addr asm ("r9");
+ register uint8_t *pending_intr_addr asm ("r10");
+ register uint8_t masked asm ("r11");
+ register unsigned long one_or_pending asm ("r8");
+
+ asm volatile (
+ ".global xen_intrin_local_irq_restore_instr\n\t"
+ "xen_intrin_local_irq_restore_instr:\n\t"
+ ".global xen_intrin_local_irq_restore_instr_start\n\t"
+ "xen_intrin_local_irq_restore_instr_start:\n\t"
+ ".global xen_intrin_local_irq_restore_stag\n\t"
+ "[xen_intrin_local_irq_restore_stag:]\n\t"
+ "tbit.nz p6,p7=%[val],%[IA64_PSR_I_BIT_IMM]\n\t"
+ "mov %[psr_i_addr]=%[XEN_PSR_I_ADDR_ADDR_IMM]\n\t"
+ ";;\n\t"
+ "ld8 %[psr_i_addr]=[%[psr_i_addr]]\n\t"
+ "(p7)mov %[one_or_pending]=%[ONE_IMM]\n\t"
+ ";;\n\t"
+ "add %[pending_intr_addr]=-1,%[psr_i_addr]\n\t"
+ ";;\n\t"
+ "(p6) ld1 %[masked]=[%[psr_i_addr]]\n\t"
+ "(p7) st1 [%[psr_i_addr]]=%[one_or_pending]\n\t"
+ ";;\n\t"
+ "(p6) st1 [%[psr_i_addr]]=r0\n\t"
+ "(p6) cmp.ne.unc p8,p0=%[masked],r0\n\t"
+ "(p6) ld1 %[one_or_pending]=[%[pending_intr_addr]]\n\t"
+ ";;\n\t"
+ "(p8) cmp.eq.unc p9,p0=%[one_or_pending],r0\n\t"
+ ";;\n\t"
+ "(p9) break %[HYPERPRIVOP_SSM_I_IMM]\n\t"
+ ".global xen_intrin_local_irq_restore_etag\n\t"
+ "[xen_intrin_local_irq_restore_etag:]\n\t"
+ ".global xen_intrin_local_irq_restore_instr_end\n\t"
+ "xen_intrin_local_irq_restore_instr_end:\n\t"
+ :
+ [psr_i_addr] "=r"(psr_i_addr),
+ [pending_intr_addr] "=r"(pending_intr_addr),
+ [masked] "=r"(masked),
+ [one_or_pending] "=r"(one_or_pending),
+
+ "=m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR))
+ :
+ [val] "r"(__val),
+ [IA64_PSR_I_BIT_IMM] "i"(IA64_PSR_I_BIT),
+ [ONE_IMM] "i"(1),
+
+ [XEN_PSR_I_ADDR_ADDR_IMM] "i"(XEN_PSR_I_ADDR_ADDR),
+ [HYPERPRIVOP_SSM_I_IMM] "i"(HYPERPRIVOP_SSM_I),
+
+ "m"(*((uint8_t *)XEN_PSR_I_ADDR_ADDR)),
+ "m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR)),
+ "m"(*(*((uint8_t **)XEN_PSR_I_ADDR_ADDR) - 1))
+ :
+ "memory",
+ "p6", /* is_psr_i_set */
+ "p7", /* not_psr_i_set */
+ "p8", /* is_masked && is_psr_i_set */
+ "p9" /* is_pending && is_masked && is_psr_i_set */
+ );
+}
+
+unsigned long __init_or_module
+xen_privop_get_psr_i(void)
+{
+ /*
+ * tmp = XEN_MAPPEDREGS->interrupt_mask_addr = XEN_PSR_I_ADDR_ADDR;
+ * tmp = *tmp
+ * tmp = *tmp;
+ * psr_i = tmp? 0: IA64_PSR_I;
+ */
+ register unsigned long psr_i asm ("r8");
+ register unsigned long tmp asm ("r9");
+
+ asm volatile (".global xen_get_psr_i_instr\n\t"
+ "xen_get_psr_i_instr:\n\t"
+ ".global xen_get_psr_i_instr_start\n\t"
+ "xen_get_psr_i_instr_start:\n\t"
+ ".global xen_get_psr_i_stag\n\t"
+ "[xen_get_psr_i_stag:]\n\t"
+ /* tmp = XEN_PSR_I_ADDR_ADDR */
+ "mov %[tmp]=%[XEN_PSR_I_ADDR_ADDR_IMM]\n\t"
+ ";;\n\t"
+ /* tmp = *tmp = *XEN_PSR_I_ADDR_ADDR */
+ "ld8 %[tmp]=[%[tmp]]\n\t"
+ /* psr_i = 0 */
+ "mov %[psr_i]=0\n\t"
+ ";;\n\t"
+ /* tmp = *(uint8_t*)tmp */
+ "ld1 %[tmp]=[%[tmp]]\n\t"
+ ";;\n\t"
+ /* if (!tmp) psr_i = IA64_PSR_I */
+ "cmp.eq.unc p6,p0=%[tmp],r0\n\t"
+ ";;\n\t"
+ "(p6) mov %[psr_i]=%[IA64_PSR_I_IMM]\n\t"
+ ".global xen_get_psr_i_etag\n\t"
+ "[xen_get_psr_i_etag:]\n\t"
+ ".global xen_get_psr_i_instr_end\n\t"
+ "xen_get_psr_i_instr_end:\n\t"
+ :
+ [tmp] "=r"(tmp),
+ [psr_i] "=r"(psr_i)
+ :
+ [XEN_PSR_I_ADDR_ADDR_IMM] "i"(XEN_PSR_I_ADDR_ADDR),
+ [IA64_PSR_I_IMM] "i"(IA64_PSR_I),
+ "m"(*((uint8_t **)XEN_PSR_I_ADDR_ADDR)),
+ "m"(**((uint8_t **)XEN_PSR_I_ADDR_ADDR))
+ :
+ "p6");
+ return psr_i;
+}
diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S
index 17ad297..2d3d5d4 100644
--- a/arch/ia64/xen/xensetup.S
+++ b/arch/ia64/xen/xensetup.S
@@ -35,6 +35,16 @@ GLOBAL_ENTRY(early_xen_setup)
(isBP) movl r28=XSI_BASE;;
(isBP) break 0x1000;;
+#ifdef CONFIG_PARAVIRT
+ /* patch privops */
+(isBP) mov r4=rp
+ ;;
+(isBP) br.call.sptk.many rp=xen_paravirt_patch
+ ;;
+(isBP) mov rp=r4
+ ;;
+#endif
+
br.ret.sptk.many rp
;;
END(early_xen_setup)
diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h
index 8261dad..fcca3f4 100644
--- a/include/asm-ia64/privop.h
+++ b/include/asm-ia64/privop.h
@@ -10,6 +10,10 @@
*
*/
+#ifdef CONFIG_PARAVIRT
+#include <asm/privop_paravirt.h>
+#endif
+
#ifdef CONFIG_XEN
#include <asm/xen/privop.h>
#endif
diff --git a/include/asm-ia64/privop_paravirt.h b/include/asm-ia64/privop_paravirt.h
new file mode 100644
index 0000000..00e4f03
--- /dev/null
+++ b/include/asm-ia64/privop_paravirt.h
@@ -0,0 +1,587 @@
+/******************************************************************************
+ * privops_paravirt.h
+ *
+ * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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_IA64_PRIVOP_PARAVIRT_H
+#define _ASM_IA64_PRIVOP_PARAVIRT_H
+
+#define PARAVIRT_INST_START 0x1
+#define PARAVIRT_INST_RFI (PARAVIRT_INST_START + 0x0)
+#define PARAVIRT_INST_RSM_DT (PARAVIRT_INST_START + 0x1)
+#define PARAVIRT_INST_SSM_DT (PARAVIRT_INST_START + 0x2)
+#define PARAVIRT_INST_COVER (PARAVIRT_INST_START + 0x3)
+#define PARAVIRT_INST_ITC_D (PARAVIRT_INST_START + 0x4)
+#define PARAVIRT_INST_ITC_I (PARAVIRT_INST_START + 0x5)
+#define PARAVIRT_INST_SSM_I (PARAVIRT_INST_START + 0x6)
+#define PARAVIRT_INST_GET_IVR (PARAVIRT_INST_START + 0x7)
+#define PARAVIRT_INST_GET_TPR (PARAVIRT_INST_START + 0x8)
+#define PARAVIRT_INST_SET_TPR (PARAVIRT_INST_START + 0x9)
+#define PARAVIRT_INST_EOI (PARAVIRT_INST_START + 0xa)
+#define PARAVIRT_INST_SET_ITM (PARAVIRT_INST_START + 0xb)
+#define PARAVIRT_INST_THASH (PARAVIRT_INST_START + 0xc)
+#define PARAVIRT_INST_PTC_GA (PARAVIRT_INST_START + 0xd)
+#define PARAVIRT_INST_ITR_D (PARAVIRT_INST_START + 0xe)
+#define PARAVIRT_INST_GET_RR (PARAVIRT_INST_START + 0xf)
+#define PARAVIRT_INST_SET_RR (PARAVIRT_INST_START + 0x10)
+#define PARAVIRT_INST_SET_KR (PARAVIRT_INST_START + 0x11)
+#define PARAVIRT_INST_FC (PARAVIRT_INST_START + 0x12)
+#define PARAVIRT_INST_GET_CPUID (PARAVIRT_INST_START + 0x13)
+#define PARAVIRT_INST_GET_PMD (PARAVIRT_INST_START + 0x14)
+#define PARAVIRT_INST_GET_EFLAG (PARAVIRT_INST_START + 0x15)
+#define PARAVIRT_INST_SET_EFLAG (PARAVIRT_INST_START + 0x16)
+#define PARAVIRT_INST_RSM_BE (PARAVIRT_INST_START + 0x17)
+#define PARAVIRT_INST_GET_PSR (PARAVIRT_INST_START + 0x18)
+#define PARAVIRT_INST_SET_RR0_TO_RR4 (PARAVIRT_INST_START + 0x19)
+
+#define PARAVIRT_BNDL_START 0x10000000
+#define PARAVIRT_BNDL_SSM_I (PARAVIRT_BNDL_START + 0x0)
+#define PARAVIRT_BNDL_RSM_I (PARAVIRT_BNDL_START + 0x1)
+#define PARAVIRT_BNDL_GET_PSR_I (PARAVIRT_BNDL_START + 0x2)
+#define PARAVIRT_BNDL_INTRIN_LOCAL_IRQ_RESTORE (PARAVIRT_BNDL_START + 0x3)
+
+/*
+ * struct task_struct* (*ia64_switch_to)(void* next_task);
+ * void *ia64_leave_syscall;
+ * void *ia64_work_processed_syscall
+ * void *ia64_leave_kernel;
+ * struct ia64_pal_retval (*pal_call_static)(u64, u64, u64, u64, u64);
+ */
+
+#define PARAVIRT_ENTRY_START 0x20000000
+#define PARAVIRT_ENTRY_SWITCH_TO (PARAVIRT_ENTRY_START + 0)
+#define PARAVIRT_ENTRY_LEAVE_SYSCALL (PARAVIRT_ENTRY_START + 1)
+#define PARAVIRT_ENTRY_WORK_PROCESSED_SYSCALL (PARAVIRT_ENTRY_START + 2)
+#define PARAVIRT_ENTRY_LEAVE_KERNEL (PARAVIRT_ENTRY_START + 3)
+#define PARAVIRT_ENTRY_PAL_CALL_STATIC (PARAVIRT_ENTRY_START + 4)
+
+
+#ifndef __ASSEMBLER__
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <asm/paravirt_alt.h>
+#include <asm/kregs.h> /* for IA64_PSR_I */
+#include <asm/xen/interface.h>
+
+/************************************************/
+/* Instructions paravirtualized for correctness */
+/************************************************/
+/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag"
+ * is not currently used (though it may be in a long-format VHPT system!) */
+#ifdef ASM_SUPPORTED
+static inline unsigned long
+paravirt_fc(unsigned long addr)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __addr asm ("r8") = addr;
+ asm volatile (paravirt_alt_inst("fc %1", PARAVIRT_INST_THASH):
+ "=r"(ia64_intri_res): "0"(__addr): "memory");
+ return ia64_intri_res;
+}
+#define paravirt_fc(addr) paravirt_fc((unsigned long)addr)
+
+static inline unsigned long
+paravirt_thash(unsigned long addr)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __addr asm ("r8") = addr;
+ asm volatile (paravirt_alt_inst("thash %0=%1", PARAVIRT_INST_THASH):
+ "=r"(ia64_intri_res): "0"(__addr));
+ return ia64_intri_res;
+}
+
+static inline unsigned long
+paravirt_get_cpuid(int index)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __index asm ("r8") = index;
+ asm volatile (paravirt_alt_inst("mov %0=cpuid[%r1]",
+ PARAVIRT_INST_GET_CPUID):
+ "=r"(ia64_intri_res): "0O"(__index));
+ return ia64_intri_res;
+}
+
+static inline unsigned long
+paravirt_get_pmd(int index)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __index asm ("r8") = index;
+ asm volatile (paravirt_alt_inst("mov %0=pmd[%1]",
+ PARAVIRT_INST_GET_PMD):
+ "=r"(ia64_intri_res): "0"(__index));
+ return ia64_intri_res;
+}
+
+static inline unsigned long
+paravirt_get_eflag(void)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ asm volatile (paravirt_alt_inst("mov %0=ar%1",
+ PARAVIRT_INST_GET_EFLAG):
+ "=r"(ia64_intri_res):
+ "i"(_IA64_REG_AR_EFLAG - _IA64_REG_AR_KR0): "memory");
+ return ia64_intri_res;
+}
+
+static inline void
+paravirt_set_eflag(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile (paravirt_alt_inst("mov ar%0=%1",
+ PARAVIRT_INST_SET_EFLAG)::
+ "i"(_IA64_REG_AR_EFLAG - _IA64_REG_AR_KR0), "r"(__val):
+ "memory");
+}
+
+/************************************************/
+/* Instructions paravirtualized for performance */
+/************************************************/
+
+static inline unsigned long
+paravirt_get_psr(void)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ asm volatile (paravirt_alt_inst("mov %0=psr", PARAVIRT_INST_GET_PSR):
+ "=r"(ia64_intri_res));
+ return ia64_intri_res;
+}
+
+static inline unsigned long
+paravirt_get_ivr(void)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ asm volatile (paravirt_alt_inst("mov %0=cr%1", PARAVIRT_INST_GET_IVR):
+ "=r"(ia64_intri_res):
+ "i" (_IA64_REG_CR_IVR - _IA64_REG_CR_DCR));
+ return ia64_intri_res;
+}
+
+static inline unsigned long
+paravirt_get_tpr(void)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ asm volatile (paravirt_alt_inst("mov %0=cr%1", PARAVIRT_INST_GET_TPR):
+ "=r"(ia64_intri_res):
+ "i" (_IA64_REG_CR_TPR - _IA64_REG_CR_DCR));
+ return ia64_intri_res;
+}
+
+static inline void
+paravirt_set_tpr(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile (paravirt_alt_inst("mov cr%0=%1", PARAVIRT_INST_SET_TPR)::
+ "i" (_IA64_REG_CR_TPR - _IA64_REG_CR_DCR), "r"(__val):
+ "memory");
+}
+
+static inline void
+paravirt_eoi(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile (paravirt_alt_inst("mov cr%0=%1", PARAVIRT_INST_EOI)::
+ "i" (_IA64_REG_CR_EOI - _IA64_REG_CR_DCR), "r"(__val):
+ "memory");
+}
+
+static inline void
+paravirt_set_itm(unsigned long val)
+{
+ register __u64 __val asm ("r8") = val;
+ asm volatile (paravirt_alt_inst("mov cr%0=%1", PARAVIRT_INST_SET_ITM)::
+ "i" (_IA64_REG_CR_ITM - _IA64_REG_CR_DCR), "r"(__val):
+ "memory");
+}
+
+static inline void
+paravirt_ptcga(unsigned long addr, unsigned long size)
+{
+ register __u64 __addr asm ("r8") = addr;
+ register __u64 __size asm ("r9") = size;
+ asm volatile (paravirt_alt_inst("ptc.ga %0,%1", PARAVIRT_INST_PTC_GA)::
+ "r"(__addr), "r"(__size): "memory");
+ ia64_dv_serialize_data();
+}
+
+static inline unsigned long
+paravirt_get_rr(unsigned long index)
+{
+ register __u64 ia64_intri_res asm ("r8");
+ register __u64 __index asm ("r8") = index;
+ asm volatile (paravirt_alt_inst("mov %0=rr[%1]", PARAVIRT_INST_GET_RR):
+ "=r"(ia64_intri_res) : "0" (__index));
+ return ia64_intri_res;
+}
+
+static inline void
+paravirt_set_rr(unsigned long index, unsigned long val)
+{
+ register __u64 __index asm ("r8") = index;
+ register __u64 __val asm ("r9") = val;
+ asm volatile (paravirt_alt_inst("mov rr[%0]=%1", PARAVIRT_INST_SET_RR)::
+ "r"(__index), "r"(__val): "memory");
+}
+
+static inline void
+paravirt_set_rr0_to_rr4(unsigned long val0, unsigned long val1,
+ unsigned long val2, unsigned long val3,
+ unsigned long val4)
+{
+ register __u64 __val0 asm ("r8") = val0;
+ register __u64 __val1 asm ("r9") = val1;
+ register __u64 __val2 asm ("r10") = val2;
+ register __u64 __val3 asm ("r11") = val3;
+ register __u64 __val4 asm ("r14") = val4;
+ asm volatile (paravirt_alt_inst("\t;;\n"
+ "\t{.mmi\n"
+ "\tmov rr[%0]=%1\n"
+ /*
+ * without this stop bit
+ * assembler complains.
+ */
+ "\t;;\n"
+ "\tmov rr[%2]=%3\n"
+ "\tnop.i 0\n"
+ "\t}\n"
+ "\t{.mmi\n"
+ "\tmov rr[%4]=%5\n"
+ "\tmov rr[%6]=%7\n"
+ "\tnop.i 0\n"
+ "\t}\n"
+ "\tmov rr[%8]=%9;;\n",
+ PARAVIRT_INST_SET_RR0_TO_RR4)::
+ "r"(0x0000000000000000UL), "r"(__val0),
+ "r"(0x2000000000000000UL), "r"(__val1),
+ "r"(0x4000000000000000UL), "r"(__val2),
+ "r"(0x6000000000000000UL), "r"(__val3),
+ "r"(0x8000000000000000UL), "r"(__val4) :
+ "memory");
+}
+
+static inline void
+paravirt_set_kr(unsigned long index, unsigned long val)
+{
+ register __u64 __index asm ("r8") = index - _IA64_REG_AR_KR0;
+ register __u64 __val asm ("r9") = val;
+
+ /*
+ * asm volatile ("break %0"::
+ * "i"(PARAVIRT_INST_SET_KR), "r"(__index), "r"(__val));
+ */
+#ifndef BUILD_BUG_ON
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#endif
+ BUILD_BUG_ON(!__builtin_constant_p(__index));
+ switch (index) {
+ case _IA64_REG_AR_KR0:
+ asm volatile (paravirt_alt_inst("mov ar%0=%2",
+ PARAVIRT_INST_SET_KR)::
+ "i" (_IA64_REG_AR_KR0 - _IA64_REG_AR_KR0),
+ "r"(__index), "r"(__val):
+ "memory");
+ break;
+ case _IA64_REG_AR_KR1:
+ asm volatile (paravirt_alt_inst("mov ar%0=%2",
+ PARAVIRT_INST_SET_KR)::
+ "i" (_IA64_REG_AR_KR1 - _IA64_REG_AR_KR0),
+ "r"(__index), "r"(__val):
+ "memory");
+ break;
+ case _IA64_REG_AR_KR2:
+ asm volatile (paravirt_alt_inst("mov ar%0=%2",
+ PARAVIRT_INST_SET_KR)::
+ "i" (_IA64_REG_AR_KR2 - _IA64_REG_AR_KR0),
+ "r"(__index), "r"(__val):
+ "memory");
+ break;
+ case _IA64_REG_AR_KR3:
+ asm volatile (paravirt_alt_inst("mov ar%0=%2",
+ PARAVIRT_INST_SET_KR)::
+ "i" (_IA64_REG_AR_KR3 - _IA64_REG_AR_KR0),
+ "r"(__index), "r"(__val):
+ "memory");
+ break;
+ case _IA64_REG_AR_KR4:
+ asm volatile (paravirt_alt_inst("mov ar%0=%2",
+ PARAVIRT_INST_SET_KR)::
+ "i" (_IA64_REG_AR_KR4 - _IA64_REG_AR_KR0),
+ "r"(__index), "r"(__val):
+ "memory");
+ break;
+ case _IA64_REG_AR_KR5:
+ asm volatile (paravirt_alt_inst("mov ar%0=%2",
+ PARAVIRT_INST_SET_KR)::
+ "i" (_IA64_REG_AR_KR5 - _IA64_REG_AR_KR0),
+ "r"(__index), "r"(__val):
+ "memory");
+ break;
+ case _IA64_REG_AR_KR6:
+ asm volatile (paravirt_alt_inst("mov ar%0=%2",
+ PARAVIRT_INST_SET_KR)::
+ "i" (_IA64_REG_AR_KR6 - _IA64_REG_AR_KR0),
+ "r"(__index), "r"(__val):
+ "memory");
+ break;
+ case _IA64_REG_AR_KR7:
+ asm volatile (paravirt_alt_inst("mov ar%0=%2",
+ PARAVIRT_INST_SET_KR)::
+ "i" (_IA64_REG_AR_KR7 - _IA64_REG_AR_KR0),
+ "r"(__index), "r"(__val):
+ "memory");
+ break;
+ default: {
+ extern void compile_error_ar_kr_index_must_be_copmile_time_constant(void);
+ compile_error_ar_kr_index_must_be_copmile_time_constant();
+ break;
+ }
+ }
+}
+#endif /* ASM_SUPPORTED */
+
+static inline unsigned long
+paravirt_getreg(unsigned long regnum)
+{
+ __u64 ia64_intri_res;
+
+ switch (regnum) {
+ case _IA64_REG_PSR:
+ ia64_intri_res = paravirt_get_psr();
+ break;
+ case _IA64_REG_CR_IVR:
+ ia64_intri_res = paravirt_get_ivr();
+ break;
+ case _IA64_REG_CR_TPR:
+ ia64_intri_res = paravirt_get_tpr();
+ break;
+ case _IA64_REG_AR_EFLAG:
+ ia64_intri_res = paravirt_get_eflag();
+ break;
+ default:
+ ia64_intri_res = __ia64_getreg(regnum);
+ break;
+ }
+ return ia64_intri_res;
+ }
+
+static inline void
+paravirt_setreg(unsigned long regnum, unsigned long val)
+{
+ switch (regnum) {
+ case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7:
+ paravirt_set_kr(regnum, val);
+ break;
+ case _IA64_REG_CR_ITM:
+ paravirt_set_itm(val);
+ break;
+ case _IA64_REG_CR_TPR:
+ paravirt_set_tpr(val);
+ break;
+ case _IA64_REG_CR_EOI:
+ paravirt_eoi(val);
+ break;
+ case _IA64_REG_AR_EFLAG:
+ paravirt_set_eflag(val);
+ break;
+ default:
+ __ia64_setreg(regnum, val);
+ break;
+ }
+}
+
+#ifdef ASM_SUPPORTED
+
+#define NOP_BUNDLE \
+ "{\n\t" \
+ "nop 0\n\t" \
+ "nop 0\n\t" \
+ "nop 0\n\t" \
+ "}\n\t"
+
+static inline void
+paravirt_ssm_i(void)
+{
+ /* five bundles */
+ asm volatile (paravirt_alt_bundle("{\n\t"
+ "ssm psr.i\n\t"
+ "nop 0\n\t"
+ "nop 0\n\t"
+ "}\n\t"
+ NOP_BUNDLE
+ NOP_BUNDLE
+ NOP_BUNDLE
+ NOP_BUNDLE,
+ PARAVIRT_BNDL_SSM_I):::
+ "r8", "r9", "r10",
+ "p6", "p7",
+ "memory");
+}
+
+static inline void
+paravirt_rsm_i(void)
+{
+ /* two budles */
+ asm volatile (paravirt_alt_bundle("{\n\t"
+ "rsm psr.i\n\t"
+ "nop 0\n\t"
+ "nop 0\n\t"
+ "}\n\t"
+ NOP_BUNDLE,
+ PARAVIRT_BNDL_RSM_I):::
+ "r8", "r9",
+ "memory");
+}
+
+static inline unsigned long
+paravirt_get_psr_i(void)
+{
+ register unsigned long psr_i asm ("r8");
+ register unsigned long mask asm ("r9");
+
+ /* three bundles */
+ asm volatile (paravirt_alt_bundle("{\n\t"
+ "mov %0=psr\n\t"
+ "mov %1=%2\n\t"
+ ";;\n\t"
+ "and %0=%0,%1\n\t"
+ "}\n\t"
+ NOP_BUNDLE
+ NOP_BUNDLE,
+ PARAVIRT_BNDL_GET_PSR_I):
+ "=r"(psr_i),
+ "=r"(mask)
+ :
+ "i"(IA64_PSR_I)
+ :
+ /* "r8", "r9", */
+ "p6");
+ return psr_i;
+}
+
+static inline void
+paravirt_intrin_local_irq_restore(unsigned long flags)
+{
+ register unsigned long __flags asm ("r8") = flags;
+
+ /* six bundles */
+ asm volatile (paravirt_alt_bundle(";;\n\t"
+ "{\n\t"
+ "cmp.ne p6,p7=%0,r0;;\n\t"
+ "(p6) ssm psr.i;\n\t"
+ "nop 0\n\t"
+ "}\n\t"
+ "{\n\t"
+ "(p7) rsm psr.i;;\n\t"
+ "(p6) srlz.d\n\t"
+ "nop 0\n\t"
+ "}\n\t"
+ NOP_BUNDLE
+ NOP_BUNDLE
+ NOP_BUNDLE
+ NOP_BUNDLE,
+ PARAVIRT_BNDL_INTRIN_LOCAL_IRQ_RESTORE)::
+ "r"(__flags) :
+ /* "r8",*/ "r9", "r10", "r11",
+ "p6", "p7", "p8", "p9",
+ "memory");
+
+}
+
+#undef NOP_BUNDLE
+
+#endif /* ASM_SUPPORTED */
+
+static inline void
+paravirt_ssm(unsigned long mask)
+{
+ if (mask == IA64_PSR_I)
+ paravirt_ssm_i();
+ else
+ __ia64_ssm(mask);
+}
+
+static inline void
+paravirt_rsm(unsigned long mask)
+{
+ if (mask == IA64_PSR_I)
+ paravirt_rsm_i();
+ else
+ __ia64_rsm(mask);
+}
+
+#if defined(ASM_SUPPORTED) && defined(CONFIG_PARAVIRT_ALT)
+
+#define IA64_PARAVIRTUALIZED_PRIVOP
+
+#define ia64_fc(addr) paravirt_fc(addr)
+#define ia64_thash(addr) paravirt_thash(addr)
+#define ia64_get_cpuid(i) paravirt_get_cpuid(i)
+#define ia64_get_pmd(i) paravirt_get_pmd(i)
+#define ia64_ptcga(addr, size) paravirt_ptcga((addr), (size))
+#define ia64_set_rr(index, val) paravirt_set_rr((index), (val))
+#define ia64_get_rr(index) paravirt_get_rr(index)
+#define ia64_getreg(regnum) paravirt_getreg(regnum)
+#define ia64_setreg(regnum, val) paravirt_setreg((regnum), (val))
+#define ia64_set_rr0_to_rr4(val0, val1, val2, val3, val4) \
+ paravirt_set_rr0_to_rr4((val0), (val1), (val2), (val3), (val4))
+
+#define ia64_ssm(mask) paravirt_ssm(mask)
+#define ia64_rsm(mask) paravirt_rsm(mask)
+#define ia64_get_psr_i() paravirt_get_psr_i()
+#define ia64_intrin_local_irq_restore(x) \
+ paravirt_intrin_local_irq_restore(x)
+
+/* the remainder of these are not performance-sensitive so its
+ * OK to not paravirtualize and just take a privop trap and emulate */
+#define ia64_hint __ia64_hint
+#define ia64_set_pmd __ia64_set_pmd
+#define ia64_itci __ia64_itci
+#define ia64_itcd __ia64_itcd
+#define ia64_itri __ia64_itri
+#define ia64_itrd __ia64_itrd
+#define ia64_tpa __ia64_tpa
+#define ia64_set_ibr __ia64_set_ibr
+#define ia64_set_pkr __ia64_set_pkr
+#define ia64_set_pmc __ia64_set_pmc
+#define ia64_get_ibr __ia64_get_ibr
+#define ia64_get_pkr __ia64_get_pkr
+#define ia64_get_pmc __ia64_get_pmc
+#define ia64_ptce __ia64_ptce
+#define ia64_ptcl __ia64_ptcl
+#define ia64_ptri __ia64_ptri
+#define ia64_ptrd __ia64_ptrd
+
+#endif /* ASM_SUPPORTED && CONFIG_PARAVIRT_ALT */
+
+#endif /* __ASSEMBLER__*/
+
+/* these routines utilize privilege-sensitive or performance-sensitive
+ * privileged instructions so the code must be replaced with
+ * paravirtualized versions */
+#ifdef CONFIG_PARAVIRT_ENTRY
+#define IA64_PARAVIRTUALIZED_ENTRY
+#define ia64_switch_to paravirt_switch_to
+#define ia64_work_processed_syscall paravirt_work_processed_syscall
+#define ia64_leave_syscall paravirt_leave_syscall
+#define ia64_leave_kernel paravirt_leave_kernel
+#define ia64_pal_call_static paravirt_pal_call_static
+#endif /* CONFIG_PARAVIRT_ENTRY */
+
+#endif /* _ASM_IA64_PRIVOP_PARAVIRT_H */
diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h
index 3caa7e9..2c70988 100644
--- a/include/asm-ia64/xen/privop.h
+++ b/include/asm-ia64/xen/privop.h
@@ -557,6 +557,18 @@ do { \
#endif /* ASM_SUPPORTED && !CONFIG_PARAVIRT_ALT */
+#ifdef CONFIG_PARAVIRT_ALT
+#if defined(CONFIG_MODULES) && defined(CONFIG_XEN)
+void xen_alt_bundle_patch_module(struct paravirt_alt_bundle_patch *start,
+ struct paravirt_alt_bundle_patch *end);
+void xen_alt_inst_patch_module(struct paravirt_alt_inst_patch *start,
+ struct paravirt_alt_inst_patch *end);
+#else
+#define xen_alt_bundle_patch_module(start, end) do { } while (0)
+#define xen_alt_inst_patch_module(start, end) do { } while (0)
+#endif
+#endif /* CONFIG_PARAVIRT_ALT */
+
#endif /* !__ASSEMBLY__ */
/* these routines utilize privilege-sensitive or performance-sensitive
@@ -573,12 +585,24 @@ do { \
#ifdef CONFIG_XEN
#ifdef __ASSEMBLY__
+#ifdef CONFIG_PARAVIRT_ENTRY
+#define BR_IF_NATIVE(target, reg_unused, pred_unused) /* nothing */
+#elif defined(CONFIG_PARAVIRT_NOP_B_PATCH)
+#define BR_IF_NATIVE(target, reg_unused, pred_unused) \
+ .body ; \
+ [1:] ; \
+ br.cond.sptk.many target;; ; \
+ .section .paravirt_nop_b, "a" ; \
+ .previous ; \
+ .xdata8 ".paravirt_nop_b", 1b
+#else
#define BR_IF_NATIVE(target, reg, pred) \
.body ; \
movl reg=running_on_xen;; ; \
ld4 reg=[reg];; ; \
cmp.eq pred,p0=reg,r0 ; \
(pred) br.cond.sptk.many target;;
+#endif
#endif /* __ASSEMBLY__ */
#endif
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (11 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 12/28] RFC: ia64/xen: xen privileged instruction intrinsics " yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 14/28] ia64/xen: ia64 domU part of xencomm yamahata
` (19 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0013-ia64-xen-introduce-xen-hypercall-routines-necessary.patch --]
[-- Type: text/plain, Size: 13303 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/xen/hypercall.S | 7 +
include/asm-ia64/xen/hypercall.h | 426 ++++++++++++++++++++++++++++++++++++++
2 files changed, 433 insertions(+), 0 deletions(-)
create mode 100644 include/asm-ia64/xen/hypercall.h
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
index a96f278..7c5242b 100644
--- a/arch/ia64/xen/hypercall.S
+++ b/arch/ia64/xen/hypercall.S
@@ -122,3 +122,10 @@ GLOBAL_ENTRY(xen_set_eflag)
END(xen_set_eflag)
#endif /* CONFIG_IA32_SUPPORT */
#endif /* ASM_SUPPORTED */
+
+GLOBAL_ENTRY(__hypercall)
+ mov r2=r37
+ break 0x1000
+ br.ret.sptk.many b0
+ ;;
+END(__hypercall)
diff --git a/include/asm-ia64/xen/hypercall.h b/include/asm-ia64/xen/hypercall.h
new file mode 100644
index 0000000..8ea2060
--- /dev/null
+++ b/include/asm-ia64/xen/hypercall.h
@@ -0,0 +1,426 @@
+/******************************************************************************
+ * hypercall.h
+ *
+ * Linux-specific hypervisor handling.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_H__
+#define __HYPERCALL_H__
+
+#ifndef __HYPERVISOR_H__
+# error "please don't include this file directly"
+#endif
+
+#include <asm/xen/xcom_hcall.h>
+struct xencomm_handle;
+extern unsigned long __hypercall(unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4,
+ unsigned long a5, unsigned long cmd);
+
+/*
+ * Assembler stubs for hyper-calls.
+ */
+
+#define _hypercall0(type, name) \
+({ \
+ long __res; \
+ __res = __hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name);\
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ 0, 0, 0, 0, __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ (unsigned long)a2, \
+ 0, 0, 0, __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ (unsigned long)a2, \
+ (unsigned long)a3, \
+ 0, 0, __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ (unsigned long)a2, \
+ (unsigned long)a3, \
+ (unsigned long)a4, \
+ 0, __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ (unsigned long)a2, \
+ (unsigned long)a3, \
+ (unsigned long)a4, \
+ (unsigned long)a5, \
+ __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+
+static inline int
+xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, sched_op, cmd, arg);
+}
+
+static inline long
+HYPERVISOR_set_timer_op(u64 timeout)
+{
+ unsigned long timeout_hi = (unsigned long)(timeout >> 32);
+ unsigned long timeout_lo = (unsigned long)timeout;
+ return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
+}
+
+static inline int
+xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list,
+ int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
+}
+
+static inline int
+xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, memory_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, event_channel_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_console_io(int cmd, int count,
+ struct xencomm_handle *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
+}
+
+static inline int
+xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, physdev_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_grant_table_op(unsigned int cmd,
+ struct xencomm_handle *uop,
+ unsigned int count)
+{
+ return _hypercall3(int, grant_table_op, cmd, uop, count);
+}
+
+int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
+
+extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg);
+
+static inline int
+xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, callback_op, cmd, arg);
+}
+
+static inline unsigned long
+xencomm_arch_hypercall_hvm_op(int cmd, void *arg)
+{
+ return _hypercall2(unsigned long, hvm_op, cmd, arg);
+}
+
+static inline long
+xencomm_arch_hypercall_vcpu_op(int cmd, int cpu, void *arg)
+{
+ return _hypercall3(long, vcpu_op, cmd, cpu, arg);
+}
+
+static inline int
+HYPERVISOR_physdev_op(int cmd, void *arg)
+{
+ switch (cmd) {
+ case PHYSDEVOP_eoi:
+ return _hypercall1(int, ia64_fast_eoi,
+ ((struct physdev_eoi *)arg)->irq);
+ default:
+ return xencomm_hypercall_physdev_op(cmd, arg);
+ }
+}
+
+static inline int
+xencomm_arch_hypercall_xenoprof_op(int op, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, xenoprof_op, op, arg);
+}
+
+static inline long
+xencomm_arch_hypercall_opt_feature(struct xencomm_handle *arg)
+{
+ return _hypercall1(long, opt_feature, arg);
+}
+
+#define xen_do_IRQ(irq, regs) \
+do { \
+ struct pt_regs *old_regs; \
+ old_regs = set_irq_regs(regs); \
+ irq_enter(); \
+ __do_IRQ(irq); \
+ irq_exit(); \
+ set_irq_regs(old_regs); \
+} while (0)
+#define irq_ctx_init(cpu) do { } while (0)
+
+#include <linux/err.h>
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+static inline unsigned long
+__HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
+{
+ return _hypercall3(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_ioremap, ioaddr, size);
+}
+
+static inline unsigned long
+HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
+{
+ unsigned long ret = ioaddr;
+ if (is_running_on_xen()) {
+ ret = __HYPERVISOR_ioremap(ioaddr, size);
+ if (unlikely(ret == -ENOSYS))
+ panic("hypercall %s failed with %ld. "
+ "Please check Xen and Linux config mismatch\n",
+ __func__, -ret);
+ else if (unlikely(IS_ERR_VALUE(ret)))
+ ret = ioaddr;
+ }
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_phystomach(unsigned long gpfn)
+{
+ return _hypercall2(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_phystomach, gpfn);
+}
+
+static inline unsigned long
+HYPERVISOR_phystomach(unsigned long gpfn)
+{
+ unsigned long ret = gpfn;
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_phystomach(gpfn);
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_machtophys(unsigned long mfn)
+{
+ return _hypercall2(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_machtophys, mfn);
+}
+
+static inline unsigned long
+HYPERVISOR_machtophys(unsigned long mfn)
+{
+ unsigned long ret = mfn;
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_machtophys(mfn);
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
+{
+ return _hypercall3(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_zap_physmap, gpfn, extent_order);
+}
+
+static inline unsigned long
+HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
+{
+ unsigned long ret = 0;
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_zap_physmap(gpfn, extent_order);
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
+ unsigned long flags, domid_t domid)
+{
+ return _hypercall5(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_add_physmap, gpfn, mfn, flags, domid);
+}
+
+static inline unsigned long
+HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
+ unsigned long flags, domid_t domid)
+{
+ unsigned long ret = 0;
+ BUG_ON(!is_running_on_xen());
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_add_physmap(gpfn, mfn, flags, domid);
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_add_physmap_with_gmfn(unsigned long gpfn, unsigned long gmfn,
+ unsigned long flags, domid_t domid)
+{
+ return _hypercall5(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_add_physmap_with_gmfn,
+ gpfn, gmfn, flags, domid);
+}
+
+static inline unsigned long
+HYPERVISOR_add_physmap_with_gmfn(unsigned long gpfn, unsigned long gmfn,
+ unsigned long flags, domid_t domid)
+{
+ unsigned long ret = 0;
+ BUG_ON(!is_running_on_xen());
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_add_physmap_with_gmfn(gpfn, gmfn,
+ flags, domid);
+ return ret;
+}
+
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
+static inline unsigned long
+HYPERVISOR_expose_p2m(unsigned long conv_start_gpfn,
+ unsigned long assign_start_gpfn,
+ unsigned long expose_size, unsigned long granule_pfn)
+{
+ return _hypercall5(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_expose_p2m, conv_start_gpfn,
+ assign_start_gpfn, expose_size, granule_pfn);
+}
+
+static inline int
+xencomm_arch_expose_foreign_p2m(unsigned long gpfn,
+ domid_t domid, struct xencomm_handle *arg,
+ unsigned long flags)
+{
+ return _hypercall5(int, ia64_dom0vp_op,
+ IA64_DOM0VP_expose_foreign_p2m,
+ gpfn, domid, arg, flags);
+}
+
+static inline int
+HYPERVISOR_unexpose_foreign_p2m(unsigned long gpfn, domid_t domid)
+{
+ return _hypercall3(int, ia64_dom0vp_op,
+ IA64_DOM0VP_unexpose_foreign_p2m, gpfn, domid);
+}
+#endif
+
+static inline int
+xencomm_arch_hypercall_perfmon_op(unsigned long cmd,
+ struct xencomm_handle *arg,
+ unsigned long count)
+{
+ return _hypercall4(int, ia64_dom0vp_op,
+ IA64_DOM0VP_perfmon, cmd, arg, count);
+}
+
+static inline int
+xencomm_arch_hypercall_fpswa_revision(struct xencomm_handle *arg)
+{
+ return _hypercall2(int, ia64_dom0vp_op,
+ IA64_DOM0VP_fpswa_revision, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_ia64_debug_op(unsigned long cmd,
+ unsigned long domain,
+ struct xencomm_handle *arg)
+{
+ return _hypercall3(int, ia64_debug_op, cmd, domain, arg);
+}
+
+static inline int
+HYPERVISOR_add_io_space(unsigned long phys_base,
+ unsigned long sparse,
+ unsigned long space_number)
+{
+ return _hypercall4(int, ia64_dom0vp_op, IA64_DOM0VP_add_io_space,
+ phys_base, sparse, space_number);
+}
+
+/* for balloon driver */
+#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
+
+/* Use xencomm to do hypercalls. */
+#define HYPERVISOR_sched_op xencomm_hypercall_sched_op
+#define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op
+#define HYPERVISOR_callback_op xencomm_hypercall_callback_op
+#define HYPERVISOR_multicall xencomm_hypercall_multicall
+#define HYPERVISOR_xen_version xencomm_hypercall_xen_version
+#define HYPERVISOR_console_io xencomm_hypercall_console_io
+#define HYPERVISOR_hvm_op xencomm_hypercall_hvm_op
+#define HYPERVISOR_memory_op xencomm_hypercall_memory_op
+#define HYPERVISOR_xenoprof_op xencomm_hypercall_xenoprof_op
+#define HYPERVISOR_perfmon_op xencomm_hypercall_perfmon_op
+#define HYPERVISOR_fpswa_revision xencomm_hypercall_fpswa_revision
+#define HYPERVISOR_suspend xencomm_hypercall_suspend
+#define HYPERVISOR_vcpu_op xencomm_hypercall_vcpu_op
+#define HYPERVISOR_opt_feature xencomm_hypercall_opt_feature
+#define HYPERVISOR_kexec_op xencomm_hypercall_kexec_op
+
+/* to compile gnttab_copy_grant_page() in drivers/xen/core/gnttab.c */
+#define HYPERVISOR_mmu_update(req, count, success_count, domid) ({ BUG(); 0; })
+
+#endif /* __HYPERCALL_H__ */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 14/28] ia64/xen: ia64 domU part of xencomm.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (12 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 15/28] ia64/xen: define xen_alloc_vm_area()/xen_free_vm_area() for ia64 arch yamahata
` (18 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0014-ia64-xen-ia64-domU-part-of-xencomm.patch --]
[-- Type: text/plain, Size: 20412 bytes --]
import ia64 specific part of xencomm which converts hypercall argument in
virtual address into pseudo physical address (guest physical address).
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/xen/xcom_asm.S | 27 +++
arch/ia64/xen/xcom_hcall.c | 458 +++++++++++++++++++++++++++++++++++++
arch/ia64/xen/xencomm.c | 108 +++++++++
include/asm-ia64/xen/xcom_hcall.h | 55 +++++
include/asm-ia64/xen/xencomm.h | 33 +++
5 files changed, 681 insertions(+), 0 deletions(-)
create mode 100644 arch/ia64/xen/xcom_asm.S
create mode 100644 arch/ia64/xen/xcom_hcall.c
create mode 100644 arch/ia64/xen/xencomm.c
create mode 100644 include/asm-ia64/xen/xcom_hcall.h
create mode 100644 include/asm-ia64/xen/xencomm.h
diff --git a/arch/ia64/xen/xcom_asm.S b/arch/ia64/xen/xcom_asm.S
new file mode 100644
index 0000000..8747908
--- /dev/null
+++ b/arch/ia64/xen/xcom_asm.S
@@ -0,0 +1,27 @@
+/*
+ * xencomm suspend support
+ * Support routines for Xen
+ *
+ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
+ */
+#include <asm/asmmacro.h>
+#include <xen/interface/xen.h>
+
+/*
+ * Stub for suspend.
+ * Just force the stacked registers to be written in memory.
+ */
+GLOBAL_ENTRY(xencomm_arch_hypercall_suspend)
+ ;;
+ alloc r20=ar.pfs,0,0,6,0
+ mov r2=__HYPERVISOR_sched_op
+ ;;
+ /* We don't want to deal with RSE. */
+ flushrs
+ mov r33=r32
+ mov r32=2 // SCHEDOP_shutdown
+ ;;
+ break 0x1000
+ ;;
+ br.ret.sptk.many b0
+END(xencomm_arch_hypercall_suspend)
diff --git a/arch/ia64/xen/xcom_hcall.c b/arch/ia64/xen/xcom_hcall.c
new file mode 100644
index 0000000..8cd9cdc
--- /dev/null
+++ b/arch/ia64/xen/xcom_hcall.c
@@ -0,0 +1,458 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Tristan Gingold <tristan.gingold@bull.net>
+ *
+ * Copyright (c) 2007
+ * Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ * consolidate mini and inline version.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/xencomm.h>
+#include <xen/interface/version.h>
+#include <xen/interface/sched.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/callback.h>
+#include <xen/interface/vcpu.h>
+#include <asm/xen/hypervisor.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/xen/xencomm.h>
+
+/* Xencomm notes:
+ * This file defines hypercalls to be used by xencomm. The hypercalls simply
+ * create inlines or mini descriptors for pointers and then call the raw arch
+ * hypercall xencomm_arch_hypercall_XXX
+ *
+ * If the arch wants to directly use these hypercalls, simply define macros
+ * in asm/xen/hypercall.h, eg:
+ * #define HYPERVISOR_sched_op xencomm_hypercall_sched_op
+ *
+ * The arch may also define HYPERVISOR_xxx as a function and do more operations
+ * before/after doing the hypercall.
+ *
+ * Note: because only inline or mini descriptors are created these functions
+ * must only be called with in kernel memory parameters.
+ */
+
+int
+xencomm_hypercall_console_io(int cmd, int count, char *str)
+{
+ return xencomm_arch_hypercall_console_io
+ (cmd, count, xencomm_map_no_alloc(str, count));
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io);
+
+int
+xencomm_hypercall_event_channel_op(int cmd, void *op)
+{
+ struct xencomm_handle *desc;
+ desc = xencomm_map_no_alloc(op, sizeof(struct evtchn_op));
+ if (desc == NULL)
+ return -EINVAL;
+
+ return xencomm_arch_hypercall_event_channel_op(cmd, desc);
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op);
+
+int
+xencomm_hypercall_xen_version(int cmd, void *arg)
+{
+ struct xencomm_handle *desc;
+ unsigned int argsize;
+
+ switch (cmd) {
+ case XENVER_version:
+ /* do not actually pass an argument */
+ return xencomm_arch_hypercall_xen_version(cmd, 0);
+ case XENVER_extraversion:
+ argsize = sizeof(struct xen_extraversion);
+ break;
+ case XENVER_compile_info:
+ argsize = sizeof(struct xen_compile_info);
+ break;
+ case XENVER_capabilities:
+ argsize = sizeof(struct xen_capabilities_info);
+ break;
+ case XENVER_changeset:
+ argsize = sizeof(struct xen_changeset_info);
+ break;
+ case XENVER_platform_parameters:
+ argsize = sizeof(struct xen_platform_parameters);
+ break;
+ case XENVER_get_features:
+ argsize = (arg == NULL) ? 0 : sizeof(struct xen_feature_info);
+ break;
+
+ default:
+ printk(KERN_DEBUG
+ "%s: unknown version op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_map_no_alloc(arg, argsize);
+ if (desc == NULL)
+ return -EINVAL;
+
+ return xencomm_arch_hypercall_xen_version(cmd, desc);
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version);
+
+int
+xencomm_hypercall_physdev_op(int cmd, void *op)
+{
+ unsigned int argsize;
+
+ switch (cmd) {
+ case PHYSDEVOP_apic_read:
+ case PHYSDEVOP_apic_write:
+ argsize = sizeof(struct physdev_apic);
+ break;
+ case PHYSDEVOP_alloc_irq_vector:
+ case PHYSDEVOP_free_irq_vector:
+ argsize = sizeof(struct physdev_irq);
+ break;
+ case PHYSDEVOP_irq_status_query:
+ argsize = sizeof(struct physdev_irq_status_query);
+ break;
+
+ default:
+ printk(KERN_DEBUG
+ "%s: unknown physdev op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_physdev_op
+ (cmd, xencomm_map_no_alloc(op, argsize));
+}
+
+static int
+xencommize_grant_table_op(struct xencomm_mini **xc_area,
+ unsigned int cmd, void *op, unsigned int count,
+ struct xencomm_handle **desc)
+{
+ struct xencomm_handle *desc1;
+ unsigned int argsize;
+
+ switch (cmd) {
+ case GNTTABOP_map_grant_ref:
+ argsize = sizeof(struct gnttab_map_grant_ref);
+ break;
+ case GNTTABOP_unmap_grant_ref:
+ argsize = sizeof(struct gnttab_unmap_grant_ref);
+ break;
+ case GNTTABOP_setup_table:
+ {
+ struct gnttab_setup_table *setup = op;
+
+ argsize = sizeof(*setup);
+
+ if (count != 1)
+ return -EINVAL;
+ desc1 = __xencomm_map_no_alloc
+ (xen_guest_handle(setup->frame_list),
+ setup->nr_frames *
+ sizeof(*xen_guest_handle(setup->frame_list)),
+ *xc_area);
+ if (desc1 == NULL)
+ return -EINVAL;
+ (*xc_area)++;
+ set_xen_guest_handle(setup->frame_list, (void *)desc1);
+ break;
+ }
+ case GNTTABOP_dump_table:
+ argsize = sizeof(struct gnttab_dump_table);
+ break;
+ case GNTTABOP_transfer:
+ argsize = sizeof(struct gnttab_transfer);
+ break;
+ case GNTTABOP_copy:
+ argsize = sizeof(struct gnttab_copy);
+ break;
+ case GNTTABOP_query_size:
+ argsize = sizeof(struct gnttab_query_size);
+ break;
+ default:
+ printk(KERN_DEBUG "%s: unknown hypercall grant table op %d\n",
+ __func__, cmd);
+ BUG();
+ }
+
+ *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area);
+ if (*desc == NULL)
+ return -EINVAL;
+ (*xc_area)++;
+
+ return 0;
+}
+
+int
+xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
+ unsigned int count)
+{
+ int rc;
+ struct xencomm_handle *desc;
+ XENCOMM_MINI_ALIGNED(xc_area, 2);
+
+ rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc);
+ if (rc)
+ return rc;
+
+ return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op);
+
+int
+xencomm_hypercall_sched_op(int cmd, void *arg)
+{
+ struct xencomm_handle *desc;
+ unsigned int argsize;
+
+ switch (cmd) {
+ case SCHEDOP_yield:
+ case SCHEDOP_block:
+ argsize = 0;
+ break;
+ case SCHEDOP_shutdown:
+ argsize = sizeof(struct sched_shutdown);
+ break;
+ case SCHEDOP_poll:
+ {
+ struct sched_poll *poll = arg;
+ struct xencomm_handle *ports;
+
+ argsize = sizeof(struct sched_poll);
+ ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports),
+ sizeof(*xen_guest_handle(poll->ports)));
+
+ set_xen_guest_handle(poll->ports, (void *)ports);
+ break;
+ }
+ default:
+ printk(KERN_DEBUG "%s: unknown sched op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_map_no_alloc(arg, argsize);
+ if (desc == NULL)
+ return -EINVAL;
+
+ return xencomm_arch_hypercall_sched_op(cmd, desc);
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op);
+
+int
+xencomm_hypercall_multicall(void *call_list, int nr_calls)
+{
+ int rc;
+ int i;
+ struct multicall_entry *mce;
+ struct xencomm_handle *desc;
+ XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2);
+
+ for (i = 0; i < nr_calls; i++) {
+ mce = (struct multicall_entry *)call_list + i;
+
+ switch (mce->op) {
+ case __HYPERVISOR_update_va_mapping:
+ case __HYPERVISOR_mmu_update:
+ /* No-op on ia64. */
+ break;
+ case __HYPERVISOR_grant_table_op:
+ rc = xencommize_grant_table_op
+ (&xc_area,
+ mce->args[0], (void *)mce->args[1],
+ mce->args[2], &desc);
+ if (rc)
+ return rc;
+ mce->args[1] = (unsigned long)desc;
+ break;
+ case __HYPERVISOR_memory_op:
+ default:
+ printk(KERN_DEBUG
+ "%s: unhandled multicall op entry op %lu\n",
+ __func__, mce->op);
+ return -ENOSYS;
+ }
+ }
+
+ desc = xencomm_map_no_alloc(call_list,
+ nr_calls * sizeof(struct multicall_entry));
+ if (desc == NULL)
+ return -EINVAL;
+
+ return xencomm_arch_hypercall_multicall(desc, nr_calls);
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall);
+
+int
+xencomm_hypercall_callback_op(int cmd, void *arg)
+{
+ unsigned int argsize;
+ switch (cmd) {
+ case CALLBACKOP_register:
+ argsize = sizeof(struct callback_register);
+ break;
+ case CALLBACKOP_unregister:
+ argsize = sizeof(struct callback_unregister);
+ break;
+ default:
+ printk(KERN_DEBUG
+ "%s: unknown callback op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_callback_op
+ (cmd, xencomm_map_no_alloc(arg, argsize));
+}
+
+static int
+xencommize_memory_reservation(struct xencomm_mini *xc_area,
+ struct xen_memory_reservation *mop)
+{
+ struct xencomm_handle *desc;
+
+ desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start),
+ mop->nr_extents *
+ sizeof(*xen_guest_handle(mop->extent_start)),
+ xc_area);
+ if (desc == NULL)
+ return -EINVAL;
+
+ set_xen_guest_handle(mop->extent_start, (void *)desc);
+ return 0;
+}
+
+int
+xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
+{
+ XEN_GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = {{NULL}, {NULL}};
+ struct xen_memory_reservation *xmr = NULL;
+ int rc;
+ struct xencomm_handle *desc;
+ unsigned int argsize;
+ XENCOMM_MINI_ALIGNED(xc_area, 2);
+
+ switch (cmd) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ case XENMEM_populate_physmap:
+ xmr = (struct xen_memory_reservation *)arg;
+ set_xen_guest_handle(extent_start_va[0],
+ xen_guest_handle(xmr->extent_start));
+
+ argsize = sizeof(*xmr);
+ rc = xencommize_memory_reservation(xc_area, xmr);
+ if (rc)
+ return rc;
+ xc_area++;
+ break;
+
+ case XENMEM_maximum_ram_page:
+ argsize = 0;
+ break;
+
+ case XENMEM_add_to_physmap:
+ argsize = sizeof(struct xen_add_to_physmap);
+ break;
+
+ default:
+ printk(KERN_DEBUG "%s: unknown memory op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ desc = xencomm_map_no_alloc(arg, argsize);
+ if (desc == NULL)
+ return -EINVAL;
+
+ rc = xencomm_arch_hypercall_memory_op(cmd, desc);
+
+ switch (cmd) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ case XENMEM_populate_physmap:
+ set_xen_guest_handle(xmr->extent_start,
+ xen_guest_handle(extent_start_va[0]));
+ break;
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op);
+
+int
+xencomm_hypercall_suspend(unsigned long srec)
+{
+ struct sched_shutdown arg;
+
+ arg.reason = SHUTDOWN_suspend;
+
+ return xencomm_arch_hypercall_suspend(
+ xencomm_map_no_alloc(&arg, sizeof(arg)));
+}
+
+long
+xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg)
+{
+ unsigned int argsize;
+ switch (cmd) {
+ case VCPUOP_register_runstate_memory_area: {
+ struct vcpu_register_runstate_memory_area *area =
+ (struct vcpu_register_runstate_memory_area *)arg;
+ argsize = sizeof(*arg);
+ set_xen_guest_handle(area->addr.h,
+ (void *)xencomm_map_no_alloc(area->addr.v,
+ sizeof(area->addr.v)));
+ break;
+ }
+
+ default:
+ printk(KERN_DEBUG "%s: unknown vcpu op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_vcpu_op(cmd, cpu,
+ xencomm_map_no_alloc(arg, argsize));
+}
+
+long
+xencomm_hypercall_opt_feature(void *arg)
+{
+ return xencomm_arch_hypercall_opt_feature(
+ xencomm_map_no_alloc(arg,
+ sizeof(struct xen_ia64_opt_feature)));
+}
+
+int
+xencomm_hypercall_fpswa_revision(unsigned int *revision)
+{
+ struct xencomm_handle *desc;
+
+ desc = xencomm_map_no_alloc(revision, sizeof(*revision));
+ if (desc == NULL)
+ return -EINVAL;
+
+ return xencomm_arch_hypercall_fpswa_revision(desc);
+}
+EXPORT_SYMBOL_GPL(xencomm_hypercall_fpswa_revision);
diff --git a/arch/ia64/xen/xencomm.c b/arch/ia64/xen/xencomm.c
new file mode 100644
index 0000000..6e9da66
--- /dev/null
+++ b/arch/ia64/xen/xencomm.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/gfp.h>
+#include <linux/mm.h>
+#include <xen/interface/xen.h>
+#include <asm/page.h>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+#include <asm/xen/xencomm.h>
+
+static unsigned long kernel_start_pa;
+
+void
+xencomm_initialize(void)
+{
+ kernel_start_pa = KERNEL_START - ia64_tpa(KERNEL_START);
+}
+
+/* Translate virtual address to physical address. */
+unsigned long
+xencomm_vtop(unsigned long vaddr)
+{
+#ifndef CONFIG_VMX_GUEST
+ struct page *page;
+ struct vm_area_struct *vma;
+#endif
+
+ if (vaddr == 0)
+ return 0;
+
+#ifdef __ia64__
+ if (REGION_NUMBER(vaddr) == 5) {
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *ptep;
+
+ /* On ia64, TASK_SIZE refers to current. It is not initialized
+ during boot.
+ Furthermore the kernel is relocatable and __pa() doesn't
+ work on addresses. */
+ if (vaddr >= KERNEL_START
+ && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE))
+ return vaddr - kernel_start_pa;
+
+ /* In kernel area -- virtually mapped. */
+ pgd = pgd_offset_k(vaddr);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ return ~0UL;
+
+ pud = pud_offset(pgd, vaddr);
+ if (pud_none(*pud) || pud_bad(*pud))
+ return ~0UL;
+
+ pmd = pmd_offset(pud, vaddr);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ return ~0UL;
+
+ ptep = pte_offset_kernel(pmd, vaddr);
+ if (!ptep)
+ return ~0UL;
+
+ return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK);
+ }
+#endif
+
+ if (vaddr > TASK_SIZE) {
+ /* kernel address */
+ return __pa(vaddr);
+ }
+
+
+#ifdef CONFIG_VMX_GUEST
+ /* No privcmd within vmx guest. */
+ return ~0UL;
+#else
+ /* XXX double-check (lack of) locking */
+ vma = find_extend_vma(current->mm, vaddr);
+ if (!vma)
+ return ~0UL;
+
+ /* We assume the page is modified. */
+ page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH);
+ if (!page)
+ return ~0UL;
+
+ return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
+#endif
+}
diff --git a/include/asm-ia64/xen/xcom_hcall.h b/include/asm-ia64/xen/xcom_hcall.h
new file mode 100644
index 0000000..adf4ba2
--- /dev/null
+++ b/include/asm-ia64/xen/xcom_hcall.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006 Tristan Gingold <tristan.gingold@bull.net>, Bull SAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 _LINUX_XENCOMM_HCALL_H_
+#define _LINUX_XENCOMM_HCALL_H_
+
+/* These function creates inline or mini descriptor for the parameters and
+ calls the corresponding xencomm_arch_hypercall_X.
+ Architectures should defines HYPERVISOR_xxx as xencomm_hypercall_xxx unless
+ they want to use their own wrapper. */
+extern int xencomm_hypercall_console_io(int cmd, int count, char *str);
+
+extern int xencomm_hypercall_event_channel_op(int cmd, void *op);
+
+extern int xencomm_hypercall_xen_version(int cmd, void *arg);
+
+extern int xencomm_hypercall_physdev_op(int cmd, void *op);
+
+extern int xencomm_hypercall_grant_table_op(unsigned int cmd, void *op,
+ unsigned int count);
+
+extern int xencomm_hypercall_sched_op(int cmd, void *arg);
+
+extern int xencomm_hypercall_multicall(void *call_list, int nr_calls);
+
+extern int xencomm_hypercall_callback_op(int cmd, void *arg);
+
+extern int xencomm_hypercall_memory_op(unsigned int cmd, void *arg);
+
+extern unsigned long xencomm_hypercall_hvm_op(int cmd, void *arg);
+
+extern int xencomm_hypercall_suspend(unsigned long srec);
+
+extern long xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg);
+
+extern long xencomm_hypercall_opt_feature(void *arg);
+
+extern int xencomm_hypercall_kexec_op(int cmd, void *arg);
+
+#endif /* _LINUX_XENCOMM_HCALL_H_ */
diff --git a/include/asm-ia64/xen/xencomm.h b/include/asm-ia64/xen/xencomm.h
new file mode 100644
index 0000000..cc27a5f
--- /dev/null
+++ b/include/asm-ia64/xen/xencomm.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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_IA64_XENCOMM_H_
+#define _ASM_IA64_XENCOMM_H_
+
+#define is_kernel_addr(x) \
+ ((PAGE_OFFSET <= (x) && \
+ (x) < (PAGE_OFFSET + (1UL << IA64_MAX_PHYS_BITS))) || \
+ (KERNEL_START <= (x) && \
+ (x) < KERNEL_START + KERNEL_TR_PAGE_SIZE))
+
+/* Must be called before any hypercall. */
+extern void xencomm_initialize(void);
+
+#include <xen/xencomm.h>
+
+#endif /* _ASM_IA64_XENCOMM_H_ */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 15/28] ia64/xen: define xen_alloc_vm_area()/xen_free_vm_area() for ia64 arch.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (13 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 14/28] ia64/xen: ia64 domU part of xencomm yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 16/28] ia64/xen: basic helper routines for xen/ia64 yamahata
` (17 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0015-ia64-xen-define-xen_alloc_vm_area-xen_free_vm_are.patch --]
[-- Type: text/plain, Size: 3317 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/xen/util.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 101 insertions(+), 0 deletions(-)
create mode 100644 arch/ia64/xen/util.c
diff --git a/arch/ia64/xen/util.c b/arch/ia64/xen/util.c
new file mode 100644
index 0000000..242a1a4
--- /dev/null
+++ b/arch/ia64/xen/util.c
@@ -0,0 +1,101 @@
+/******************************************************************************
+ * arch/ia64/xen/util.c
+ * This file is the ia64 counterpart of drivers/xen/util.c
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/mm.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <xen/interface/memory.h>
+#include <asm/xen/hypercall.h>
+
+struct vm_struct *xen_alloc_vm_area(unsigned long size)
+{
+ int order;
+ unsigned long virt;
+ unsigned long nr_pages;
+ struct vm_struct *area;
+
+ order = get_order(size);
+ virt = __get_free_pages(GFP_KERNEL, order);
+ if (virt == 0)
+ goto err0;
+ nr_pages = 1 << order;
+ scrub_pages(virt, nr_pages);
+
+ area = kmalloc(sizeof(*area), GFP_KERNEL);
+ if (area == NULL)
+ goto err1;
+
+ area->flags = VM_IOREMAP;
+ area->addr = (void *)virt;
+ area->size = size;
+ area->pages = NULL;
+ area->nr_pages = nr_pages;
+ area->phys_addr = 0; /* xenbus_map_ring_valloc uses this field! */
+
+ return area;
+
+err1:
+ free_pages(virt, order);
+err0:
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(xen_alloc_vm_area);
+
+void xen_free_vm_area(struct vm_struct *area)
+{
+ unsigned int order = get_order(area->size);
+ unsigned long i;
+ unsigned long phys_addr = __pa(area->addr);
+
+ /* This area is used for foreign page mappping.
+ * So underlying machine page may not be assigned. */
+ for (i = 0; i < (1 << order); i++) {
+ unsigned long ret;
+ unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i;
+ struct xen_memory_reservation reservation = {
+ .nr_extents = 1,
+ .address_bits = 0,
+ .extent_order = 0,
+ .domid = DOMID_SELF
+ };
+ set_xen_guest_handle(reservation.extent_start, &gpfn);
+ ret = HYPERVISOR_memory_op(XENMEM_populate_physmap,
+ &reservation);
+ BUG_ON(ret != 1);
+ }
+ free_pages((unsigned long)area->addr, order);
+ kfree(area);
+}
+EXPORT_SYMBOL_GPL(xen_free_vm_area);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 16/28] ia64/xen: basic helper routines for xen/ia64.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (14 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 15/28] ia64/xen: define xen_alloc_vm_area()/xen_free_vm_area() for ia64 arch yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 17/28] ia64/xen: domU initialization code yamahata
` (16 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0016-ia64-xen-basic-helper-routines-for-xen-ia64.patch --]
[-- Type: text/plain, Size: 12472 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/xen/hypervisor.c | 228 +++++++++++++++++++++++++++++++++++++
include/asm-ia64/xen/hypervisor.h | 194 +++++++++++++++++++++++++++++++
2 files changed, 422 insertions(+), 0 deletions(-)
create mode 100644 arch/ia64/xen/hypervisor.c
diff --git a/arch/ia64/xen/hypervisor.c b/arch/ia64/xen/hypervisor.c
new file mode 100644
index 0000000..4e5791d
--- /dev/null
+++ b/arch/ia64/xen/hypervisor.c
@@ -0,0 +1,228 @@
+/******************************************************************************
+ * include/asm-ia64/shadow.h
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/spinlock.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/efi.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/meminit.h>
+#include <asm/xen/hypervisor.h>
+#include <asm/xen/hypercall.h>
+#include <xen/interface/memory.h>
+
+struct shared_info *HYPERVISOR_shared_info __read_mostly =
+ (struct shared_info *)XSI_BASE;
+EXPORT_SYMBOL(HYPERVISOR_shared_info);
+
+DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
+#ifdef notyet
+DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
+#endif
+
+struct start_info *xen_start_info;
+EXPORT_SYMBOL(xen_start_info);
+
+EXPORT_SYMBOL(running_on_xen);
+
+EXPORT_SYMBOL(__hypercall);
+
+/* Stolen from arch/x86/xen/enlighten.c */
+/*
+ * Flag to determine whether vcpu info placement is available on all
+ * VCPUs. We assume it is to start with, and then set it to zero on
+ * the first failure. This is because it can succeed on some VCPUs
+ * and not others, since it can involve hypervisor memory allocation,
+ * or because the guest failed to guarantee all the appropriate
+ * constraints on all VCPUs (ie buffer can't cross a page boundary).
+ *
+ * Note that any particular CPU may be using a placed vcpu structure,
+ * but we can only optimise if the all are.
+ *
+ * 0: not available, 1: available
+ */
+#ifdef notyet
+static int have_vcpu_info_placement;
+#endif
+
+static void __init xen_vcpu_setup(int cpu)
+{
+/* on Xen/IA64 VCPUOP_register_vcpu_info isn't supported */
+#ifdef notyet
+ struct vcpu_register_vcpu_info info;
+ int err;
+ struct vcpu_info *vcpup;
+#endif
+
+ per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+
+#ifdef notyet
+ if (!have_vcpu_info_placement)
+ return; /* already tested, not available */
+
+ vcpup = &per_cpu(xen_vcpu_info, cpu);
+
+ info.mfn = virt_to_mfn(vcpup);
+ info.offset = offset_in_page(vcpup);
+
+ printk(KERN_DEBUG
+ "trying to map vcpu_info %d at %p, mfn %llx, offset %d\n",
+ cpu, vcpup, info.mfn, info.offset);
+
+ /* Check to see if the hypervisor will put the vcpu_info
+ structure where we want it, which allows direct access via
+ a percpu-variable. */
+ err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info);
+
+ if (err) {
+ printk(KERN_DEBUG "register_vcpu_info failed: err=%d\n", err);
+ have_vcpu_info_placement = 0;
+ } else {
+ /* This cpu is using the registered vcpu info, even if
+ later ones fail to. */
+ per_cpu(xen_vcpu, cpu) = vcpup;
+
+ printk(KERN_DEBUG "cpu %d using vcpu_info at %p\n",
+ cpu, vcpup);
+ }
+#endif
+}
+
+void __init xen_setup_vcpu_info_placement(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu)
+ xen_vcpu_setup(cpu);
+}
+
+void __init
+xen_setup(char **cmdline_p)
+{
+ extern void dig_setup(char **cmdline_p);
+
+ if (ia64_platform_is("xen"))
+ dig_setup(cmdline_p);
+}
+
+void __cpuinit
+xen_cpu_init(void)
+{
+ extern void xen_smp_intr_init(void);
+ xen_smp_intr_init();
+}
+
+/****************************************************************************
+ * grant table hack
+ * cmd: GNTTABOP_xxx
+ */
+
+#include <linux/mm.h>
+#include <xen/interface/xen.h>
+#include <xen/grant_table.h>
+
+int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+ unsigned long max_nr_gframes,
+ struct grant_entry **__shared)
+{
+ *__shared = __va(frames[0] << PAGE_SHIFT);
+ return 0;
+}
+
+void arch_gnttab_unmap_shared(struct grant_entry *shared,
+ unsigned long nr_gframes)
+{
+ /* nothing */
+}
+
+static void
+gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop)
+{
+ uint32_t flags;
+
+ flags = uop->flags;
+
+ if (flags & GNTMAP_host_map) {
+ if (flags & GNTMAP_application_map) {
+ printk(KERN_DEBUG
+ "GNTMAP_application_map is not supported yet: "
+ "flags 0x%x\n", flags);
+ BUG();
+ }
+ if (flags & GNTMAP_contains_pte) {
+ printk(KERN_DEBUG
+ "GNTMAP_contains_pte is not supported yet: "
+ "flags 0x%x\n", flags);
+ BUG();
+ }
+ } else if (flags & GNTMAP_device_map) {
+ printk("GNTMAP_device_map is not supported yet 0x%x\n", flags);
+ BUG(); /* XXX not yet. actually this flag is not used. */
+ } else {
+ BUG();
+ }
+}
+
+int
+HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
+{
+ if (cmd == GNTTABOP_map_grant_ref) {
+ unsigned int i;
+ for (i = 0; i < count; i++) {
+ gnttab_map_grant_ref_pre(
+ (struct gnttab_map_grant_ref *)uop + i);
+ }
+ }
+ return xencomm_hypercall_grant_table_op(cmd, uop, count);
+}
+EXPORT_SYMBOL(HYPERVISOR_grant_table_op);
+
+/**************************************************************************
+ * opt feature
+ */
+void
+xen_ia64_enable_opt_feature(void)
+{
+ /* Enable region 7 identity map optimizations in Xen */
+ struct xen_ia64_opt_feature optf;
+
+ optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG7;
+ optf.on = XEN_IA64_OPTF_ON;
+ optf.pgprot = pgprot_val(PAGE_KERNEL);
+ optf.key = 0; /* No key on linux. */
+ HYPERVISOR_opt_feature(&optf);
+}
+
+/**************************************************************************
+ * suspend/resume
+ */
+void
+xen_post_suspend(int suspend_cancelled)
+{
+ if (suspend_cancelled)
+ return;
+
+ xen_ia64_enable_opt_feature();
+ /* add more if necessary */
+}
diff --git a/include/asm-ia64/xen/hypervisor.h b/include/asm-ia64/xen/hypervisor.h
index 4ee50c9..c8ae8e8 100644
--- a/include/asm-ia64/xen/hypervisor.h
+++ b/include/asm-ia64/xen/hypervisor.h
@@ -42,9 +42,203 @@ extern const int running_on_xen;
# define is_running_on_xen() (1)
# else /* CONFIG_VMX_GUEST */
# define is_running_on_xen() (0)
+# define HYPERVISOR_ioremap(offset, size) (offset)
# endif /* CONFIG_VMX_GUEST */
#endif /* CONFIG_XEN */
+#if defined(CONFIG_XEN) || defined(CONFIG_VMX_GUEST)
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/version.h> /* to compile feature.c */
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/sched.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/percpu.h>
+#ifdef CONFIG_XEN
+#include <asm/xen/hypercall.h>
+#endif
+
+extern struct shared_info *HYPERVISOR_shared_info;
+extern struct start_info *xen_start_info;
+
+DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
+void __init xen_setup_vcpu_info_placement(void);
+void force_evtchn_callback(void);
+
+struct vm_struct *xen_alloc_vm_area(unsigned long size);
+void xen_free_vm_area(struct vm_struct *area);
+
+/* Turn jiffies into Xen system time. XXX Implement me. */
+#define jiffies_to_st(j) 0
+
+static inline int
+HYPERVISOR_yield(
+ void)
+{
+ int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
+
+ return rc;
+}
+
+static inline int
+HYPERVISOR_block(
+ void)
+{
+ int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
+
+ return rc;
+}
+
+static inline int
+HYPERVISOR_shutdown(
+ unsigned int reason)
+{
+ struct sched_shutdown sched_shutdown = {
+ .reason = reason
+ };
+
+ int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+
+ return rc;
+}
+
+static inline int
+HYPERVISOR_poll(
+ evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
+{
+ struct sched_poll sched_poll = {
+ .nr_ports = nr_ports,
+ .timeout = jiffies_to_st(timeout)
+ };
+
+ int rc;
+
+ set_xen_guest_handle(sched_poll.ports, ports);
+ rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
+
+ return rc;
+}
+
+#ifndef CONFIG_VMX_GUEST
+/* for drivers/xen/privcmd/privcmd.c */
+#define machine_to_phys_mapping 0
+struct vm_area_struct;
+int direct_remap_pfn_range(struct vm_area_struct *vma,
+ unsigned long address,
+ unsigned long mfn,
+ unsigned long size,
+ pgprot_t prot,
+ domid_t domid);
+struct file;
+int privcmd_enforce_singleshot_mapping(struct vm_area_struct *vma);
+int privcmd_mmap(struct file *file, struct vm_area_struct *vma);
+#define HAVE_ARCH_PRIVCMD_MMAP
+
+/* for drivers/xen/balloon/balloon.c */
+#ifdef CONFIG_XEN_SCRUB_PAGES
+#define scrub_pages(_p, _n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
+#else
+#define scrub_pages(_p, _n) ((void)0)
+#endif
+#define pte_mfn(_x) pte_pfn(_x)
+#define phys_to_machine_mapping_valid(_x) (1)
+
+void xen_contiguous_bitmap_init(unsigned long end_pfn);
+int __xen_create_contiguous_region(unsigned long vstart, unsigned int order,
+ unsigned int address_bits);
+static inline int
+xen_create_contiguous_region(unsigned long vstart,
+ unsigned int order, unsigned int address_bits)
+{
+ int ret = 0;
+ if (is_running_on_xen()) {
+ ret = __xen_create_contiguous_region(vstart, order,
+ address_bits);
+ }
+ return ret;
+}
+
+void __xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
+static inline void
+xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
+{
+ if (is_running_on_xen())
+ __xen_destroy_contiguous_region(vstart, order);
+}
+
+struct page;
+
+int xen_limit_pages_to_max_mfn(struct page *pages, unsigned int order,
+ unsigned int address_bits);
+
+/* For drivers/xen/core/machine_reboot.c */
+#define HAVE_XEN_POST_SUSPEND
+void xen_post_suspend(int suspend_cancelled);
+
+/* For setup_arch() in arch/ia64/kernel/setup.c */
+void xen_ia64_enable_opt_feature(void);
+#endif /* !CONFIG_VMX_GUEST */
+
+#define __pte_ma(_x) ((pte_t) {(_x)}) /* unmodified use */
+#define mfn_pte(_x, _y) __pte_ma(0) /* unmodified use */
+
+/* for netfront.c, netback.c */
+#define MULTI_UVMFLAGS_INDEX 0 /* XXX any value */
+
+static inline void
+MULTI_update_va_mapping(
+ struct multicall_entry *mcl, unsigned long va,
+ pte_t new_val, unsigned long flags)
+{
+ mcl->op = __HYPERVISOR_update_va_mapping;
+ mcl->result = 0;
+}
+
+static inline void
+MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
+ void *uop, unsigned int count)
+{
+ mcl->op = __HYPERVISOR_grant_table_op;
+ mcl->args[0] = cmd;
+ mcl->args[1] = (unsigned long)uop;
+ mcl->args[2] = count;
+}
+
+static inline void
+MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
+ int count, int *success_count, domid_t domid)
+{
+ mcl->op = __HYPERVISOR_mmu_update;
+ mcl->args[0] = (unsigned long)req;
+ mcl->args[1] = count;
+ mcl->args[2] = (unsigned long)success_count;
+ mcl->args[3] = domid;
+}
+
+/*
+ * for blktap.c
+ * int create_lookup_pte_addr(struct mm_struct *mm,
+ * unsigned long address,
+ * uint64_t *ptep);
+ */
+#define create_lookup_pte_addr(mm, address, ptep) \
+ ({ \
+ printk(KERN_EMERG \
+ "%s:%d " \
+ "create_lookup_pte_addr() isn't supported.\n", \
+ __func__, __LINE__); \
+ BUG(); \
+ (-ENOSYS); \
+ })
+
+#endif /* CONFIG_XEN || CONFIG_VMX_GUEST */
+
#ifdef CONFIG_XEN_PRIVILEGED_GUEST
#define is_initial_xendomain() \
(is_running_on_xen() ? xen_start_info->flags & SIF_INITDOMAIN : 0)
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 17/28] ia64/xen: domU initialization code.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (15 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 16/28] ia64/xen: basic helper routines for xen/ia64 yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 18/28] ia64/xen: iosapic paravirtualization yamahata
` (15 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0017-ia64-xen-domU-initialization-code.patch --]
[-- Type: text/plain, Size: 7115 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/Makefile | 12 ++++-
arch/ia64/kernel/setup.c | 121 ++++++++++++++++++++++++++++++++++++++++++++
arch/ia64/kernel/smpboot.c | 4 ++
arch/ia64/xen/Makefile | 4 ++
4 files changed, 139 insertions(+), 2 deletions(-)
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index b916ccf..36be3bf 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -45,6 +45,12 @@ ifeq ($(call cc-version),0304)
endif
KBUILD_CFLAGS += $(cflags-y)
+
+cppflags-$(CONFIG_XEN) += \
+ -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION)
+
+KBUILD_CPPFLAGS += $(cppflags-y)
+
head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
libs-y += arch/ia64/lib/
@@ -54,7 +60,9 @@ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/
core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/
core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/
+core-$(CONFIG_IA64_XEN) += arch/ia64/dig/
core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/
+core-$(CONFIG_XEN) += arch/ia64/xen/
drivers-$(CONFIG_PCI) += arch/ia64/pci/
drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
@@ -87,8 +95,8 @@ CLEAN_FILES += vmlinux.gz bootloader
boot: lib/lib.a vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@
-install: vmlinux.gz
- sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
+install:
+ -yes | sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
define archhelp
echo '* compressed - Build compressed kernel image'
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index ebd1a09..0c103b5 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -61,6 +61,12 @@
#include <asm/system.h>
#include <asm/unistd.h>
#include <asm/hpsim.h>
+#ifdef CONFIG_XEN
+#include <xen/features.h>
+#include <asm/xen/hypervisor.h>
+#include <asm/xen/xencomm.h>
+#endif
+#include <linux/dma-mapping.h>
#if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
# error "struct cpuinfo_ia64 too big!"
@@ -71,6 +77,34 @@ unsigned long __per_cpu_offset[NR_CPUS];
EXPORT_SYMBOL(__per_cpu_offset);
#endif
+#ifdef CONFIG_XEN
+static void
+xen_panic_hypercall(struct unw_frame_info *info, void *arg)
+{
+ current->thread.ksp = (__u64)info->sw - 16;
+ HYPERVISOR_shutdown(SHUTDOWN_crash);
+ /* we're never actually going to get here... */
+}
+
+static int
+xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ unw_init_running(xen_panic_hypercall, NULL);
+ /* we're never actually going to get here... */
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block xen_panic_block = {
+ xen_panic_event, NULL, 0 /* try to go last */
+};
+
+void xen_pm_power_off(void)
+{
+ local_irq_disable();
+ HYPERVISOR_shutdown(SHUTDOWN_poweroff);
+}
+#endif
+
DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
DEFINE_PER_CPU(unsigned long, local_per_cpu_offset);
unsigned long ia64_cycles_per_usec;
@@ -288,6 +322,14 @@ reserve_memory (void)
rsvd_region[n].end = (unsigned long) ia64_imva(_end);
n++;
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ rsvd_region[n].start = (unsigned long)__va((HYPERVISOR_shared_info->arch.start_info_pfn << PAGE_SHIFT));
+ rsvd_region[n].end = rsvd_region[n].start + PAGE_SIZE;
+ n++;
+ }
+#endif
+
#ifdef CONFIG_BLK_DEV_INITRD
if (ia64_boot_param->initrd_start) {
rsvd_region[n].start = (unsigned long)__va(ia64_boot_param->initrd_start);
@@ -466,6 +508,24 @@ setup_arch (char **cmdline_p)
{
unw_init();
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ struct shared_info *s = HYPERVISOR_shared_info;
+ xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT);
+
+ /* Must be done before any hypercall. */
+ xencomm_initialize();
+
+ xen_setup_features();
+ /* Register a call for panic conditions. */
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &xen_panic_block);
+ pm_power_off = xen_pm_power_off;
+
+ xen_ia64_enable_opt_feature();
+ }
+#endif
+
ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
*cmdline_p = __va(ia64_boot_param->command_line);
@@ -518,6 +578,59 @@ setup_arch (char **cmdline_p)
acpi_boot_init();
#endif
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ printk(KERN_INFO
+ "Running on Xen! start_info_pfn=0x%lx nr_pages=%ld "
+ "flags=0x%x\n",
+ HYPERVISOR_shared_info->arch.start_info_pfn,
+ xen_start_info->nr_pages, xen_start_info->flags);
+
+ /*
+ * If a console= is NOT specified, we assume using the
+ * xencons console is desired. By default, this is xvc0
+ * for both dom0 and domU.
+ */
+ if (!strstr(*cmdline_p, "console=")) {
+ char *p, *q, name[5] = "xvc";
+ int offset = 0;
+
+#if defined(CONFIG_VGA_CONSOLE)
+ /*
+ * conswitchp might be set intelligently from the
+ * PCDP code. If set to VGA console, use it.
+ */
+ if (is_initial_xendomain() && conswitchp == &vga_con)
+ strncpy(name, "tty", 3);
+#endif
+
+ p = strstr(*cmdline_p, "xencons=");
+
+ if (p) {
+ p += 8;
+ if (!strncmp(p, "ttyS", 4)) {
+ strncpy(name, p, 4);
+ p += 4;
+ offset = simple_strtol(p, &q, 10);
+ if (p == q)
+ offset = 0;
+ } else if (!strncmp(p, "tty", 3) ||
+ !strncmp(p, "xvc", 3)) {
+ strncpy(name, p, 3);
+ p += 3;
+ offset = simple_strtol(p, &q, 10);
+ if (p == q)
+ offset = 0;
+ } else if (!strncmp(p, "off", 3))
+ offset = -1;
+ }
+
+ if (offset >= 0)
+ add_preferred_console(name, offset, NULL);
+ }
+ }
+#endif
+
#ifdef CONFIG_VT
if (!conswitchp) {
# if defined(CONFIG_DUMMY_CONSOLE)
@@ -537,6 +650,14 @@ setup_arch (char **cmdline_p)
#endif
/* enable IA-64 Machine Check Abort Handling unless disabled */
+#ifdef CONFIG_XEN
+ if (is_running_on_xen() && !is_initial_xendomain()) {
+ nomca = 1;
+#if !defined(CONFIG_VT) || !defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = NULL;
+#endif
+ }
+#endif
if (!nomca)
ia64_mca_init();
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 32ee597..2da0a00 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -642,6 +642,10 @@ void __devinit smp_prepare_boot_cpu(void)
cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), cpu_callin_map);
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+#ifdef CONFIG_XEN
+ if (is_running_on_xen())
+ xen_setup_vcpu_info_placement();
+#endif
}
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile
index c219358..91ffafe 100644
--- a/arch/ia64/xen/Makefile
+++ b/arch/ia64/xen/Makefile
@@ -2,6 +2,10 @@
# Makefile for Xen components
#
+obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o \
+ hypervisor.o util.o xencomm.o xcom_hcall.o xcom_asm.o
+
+obj-$(CONFIG_IA64_GENERIC) += machvec.o
obj-$(CONFIG_PARAVIRT_ALT) += paravirt_xen.o privops_asm.o privops_c.o
obj-$(CONFIG_PARAVIRT_NOP_B_PATCH) += paravirt_xen.o
obj-$(CONFIG_PARAVIRT_ENTRY) += paravirt_xen.o
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 18/28] ia64/xen: iosapic paravirtualization
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (16 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 17/28] ia64/xen: domU initialization code yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 19/28] ia64/xen: xen domU irq chip introducing some helper functions, xen_send_ipi yamahata
` (14 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0018-ia64-xen-iosapic-paravirtualization.patch --]
[-- Type: text/plain, Size: 4178 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/iosapic.c | 89 ++++++++++++++++++++++++++++++++++++++++---
include/asm-ia64/iosapic.h | 2 +
2 files changed, 84 insertions(+), 7 deletions(-)
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 398e2fd..5915d7e 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -157,6 +157,79 @@ static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */
static int iosapic_kmalloc_ok;
static LIST_HEAD(free_rte_list);
+#ifdef CONFIG_XEN
+#include <xen/interface/xen.h>
+#include <xen/interface/physdev.h>
+#include <asm/xen/hypervisor.h>
+static inline unsigned int
+xen_iosapic_read(char __iomem *iosapic, unsigned int reg)
+{
+ struct physdev_apic apic_op;
+ int ret;
+
+ apic_op.apic_physbase = (unsigned long)iosapic -
+ __IA64_UNCACHED_OFFSET;
+ apic_op.reg = reg;
+ ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
+ if (ret)
+ return ret;
+ return apic_op.value;
+}
+
+static inline void
+xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
+{
+ struct physdev_apic apic_op;
+
+ apic_op.apic_physbase = (unsigned long)iosapic -
+ __IA64_UNCACHED_OFFSET;
+ apic_op.reg = reg;
+ apic_op.value = val;
+ HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op);
+}
+
+static inline unsigned int
+__iosapic_read(char __iomem *iosapic, unsigned int reg)
+{
+ if (!is_running_on_xen()) {
+ writel(reg, iosapic + IOSAPIC_REG_SELECT);
+ return readl(iosapic + IOSAPIC_WINDOW);
+ } else
+ return xen_iosapic_read(iosapic, reg);
+}
+
+static inline void
+__iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
+{
+ if (!is_running_on_xen()) {
+ writel(reg, iosapic + IOSAPIC_REG_SELECT);
+ writel(val, iosapic + IOSAPIC_WINDOW);
+ } else
+ xen_iosapic_write(iosapic, reg, val);
+}
+
+int xen_assign_irq_vector(int irq)
+{
+ struct physdev_irq irq_op;
+
+ irq_op.irq = irq;
+ if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op))
+ return -ENOSPC;
+
+ return irq_op.vector;
+}
+
+void xen_free_irq_vector(int vector)
+{
+ struct physdev_irq irq_op;
+
+ irq_op.vector = vector;
+ if (HYPERVISOR_physdev_op(PHYSDEVOP_free_irq_vector, &irq_op))
+ printk(KERN_WARNING "%s: xen_free_irq_vecotr fail vector=%d\n",
+ __func__, vector);
+}
+#endif /* XEN */
+
static inline void
iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
{
@@ -269,19 +342,15 @@ nop (unsigned int irq)
/* do nothing... */
}
-
#ifdef CONFIG_KEXEC
void
kexec_disable_iosapic(void)
{
struct iosapic_intr_info *info;
struct iosapic_rte_info *rte;
- ia64_vector vec;
- int irq;
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- info = &iosapic_intr_info[irq];
- vec = irq_to_vector(irq);
+ u8 vec = 0;
+ for (info = iosapic_intr_info; info <
+ iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) {
list_for_each_entry(rte, &info->rtes,
rte_list) {
iosapic_write(rte->iosapic,
@@ -635,6 +704,9 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
iosapic_intr_info[irq].dmode = delivery;
iosapic_intr_info[irq].trigger = trigger;
+ if (is_running_on_xen())
+ return 0;
+
if (trigger == IOSAPIC_EDGE)
irq_type = &irq_type_iosapic_edge;
else
@@ -987,6 +1059,9 @@ iosapic_system_init (int system_pcat_compat)
}
pcat_compat = system_pcat_compat;
+ if (is_running_on_xen())
+ return;
+
if (pcat_compat) {
/*
* Disable the compatibility mode interrupts (8259 style),
diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
index a3a4288..7ed8e4f 100644
--- a/include/asm-ia64/iosapic.h
+++ b/include/asm-ia64/iosapic.h
@@ -55,6 +55,7 @@
#define NR_IOSAPICS 256
+#ifndef CONFIG_XEN
static inline unsigned int __iosapic_read(char __iomem *iosapic, unsigned int reg)
{
writel(reg, iosapic + IOSAPIC_REG_SELECT);
@@ -66,6 +67,7 @@ static inline void __iosapic_write(char __iomem *iosapic, unsigned int reg, u32
writel(reg, iosapic + IOSAPIC_REG_SELECT);
writel(val, iosapic + IOSAPIC_WINDOW);
}
+#endif
static inline void iosapic_eoi(char __iomem *iosapic, u32 vector)
{
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 19/28] ia64/xen: xen domU irq chip introducing some helper functions, xen_send_ipi.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (17 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 18/28] ia64/xen: iosapic paravirtualization yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 20/28] ia64/xen: domU xen machine vector without dma api yamahata
` (13 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0019-ia64-xen-xen-domU-irq-chip-introducing-some-helper.patch --]
[-- Type: text/plain, Size: 14058 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/irq_ia64.c | 363 ++++++++++++++++++++++++++++++++++++++++++-
arch/ia64/xen/hypercall.S | 10 ++
include/asm-ia64/hw_irq.h | 10 ++
include/asm-ia64/irq.h | 33 ++++
4 files changed, 414 insertions(+), 2 deletions(-)
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 0b52f19..b5dcb49 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -30,6 +30,9 @@
#include <linux/threads.h>
#include <linux/bitops.h>
#include <linux/irq.h>
+#ifdef CONFIG_XEN
+#include <linux/cpu.h>
+#endif
#include <asm/delay.h>
#include <asm/intrinsics.h>
@@ -204,6 +207,13 @@ assign_irq_vector (int irq)
vector = -ENOSPC;
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ extern int xen_assign_irq_vector(int);
+ return xen_assign_irq_vector(irq);
+ }
+#endif
+
spin_lock_irqsave(&vector_lock, flags);
for_each_online_cpu(cpu) {
domain = vector_allocation_domain(cpu);
@@ -227,6 +237,14 @@ free_irq_vector (int vector)
if (vector < IA64_FIRST_DEVICE_VECTOR ||
vector > IA64_LAST_DEVICE_VECTOR)
return;
+
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ extern void xen_free_irq_vector(int);
+ xen_free_irq_vector(vector);
+ return;
+ }
+#endif
clear_irq_vector(vector);
}
@@ -555,12 +573,343 @@ static struct irqaction tlb_irqaction = {
#endif
+#ifdef CONFIG_XEN
+#include <xen/events.h>
+#include <xen/interface/callback.h>
+
+static DEFINE_PER_CPU(int, timer_irq) = -1;
+static DEFINE_PER_CPU(int, ipi_irq) = -1;
+static DEFINE_PER_CPU(int, resched_irq) = -1;
+static DEFINE_PER_CPU(int, cmc_irq) = -1;
+static DEFINE_PER_CPU(int, cmcp_irq) = -1;
+static DEFINE_PER_CPU(int, cpep_irq) = -1;
+static char timer_name[NR_CPUS][15];
+static char ipi_name[NR_CPUS][15];
+static char resched_name[NR_CPUS][15];
+static char cmc_name[NR_CPUS][15];
+static char cmcp_name[NR_CPUS][15];
+static char cpep_name[NR_CPUS][15];
+
+struct saved_irq {
+ unsigned int irq;
+ struct irqaction *action;
+};
+/* 16 should be far optimistic value, since only several percpu irqs
+ * are registered early.
+ */
+#define MAX_LATE_IRQ 16
+static struct saved_irq saved_percpu_irqs[MAX_LATE_IRQ];
+static unsigned short late_irq_cnt = 0;
+static unsigned short saved_irq_cnt = 0;
+static int xen_slab_ready = 0;
+
+#ifdef CONFIG_SMP
+/* Dummy stub. Though we may check RESCHEDULE_VECTOR before __do_IRQ,
+ * it ends up to issue several memory accesses upon percpu data and
+ * thus adds unnecessary traffic to other paths.
+ */
+static irqreturn_t
+xen_dummy_handler(int irq, void *dev_id)
+{
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction xen_resched_irqaction = {
+ .handler = xen_dummy_handler,
+ .flags = IRQF_DISABLED,
+ .name = "resched"
+};
+
+static struct irqaction xen_tlb_irqaction = {
+ .handler = xen_dummy_handler,
+ .flags = IRQF_DISABLED,
+ .name = "tlb_flush"
+};
+#endif
+
+/*
+ * This is xen version percpu irq registration, which needs bind
+ * to xen specific evtchn sub-system. One trick here is that xen
+ * evtchn binding interface depends on kmalloc because related
+ * port needs to be freed at device/cpu down. So we cache the
+ * registration on BSP before slab is ready and then deal them
+ * at later point. For rest instances happening after slab ready,
+ * we hook them to xen evtchn immediately.
+ *
+ * FIXME: MCA is not supported by far, and thus "nomca" boot param is
+ * required.
+ */
+static void
+xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
+ struct irqaction *action, int save)
+{
+ irq_desc_t *desc;
+ int irq = 0;
+
+ if (xen_slab_ready) {
+ switch (vec) {
+ case IA64_TIMER_VECTOR:
+ sprintf(timer_name[cpu], "%s%d", action->name, cpu);
+ irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu,
+ action->handler, action->flags,
+ timer_name[cpu], action->dev_id);
+ per_cpu(timer_irq, cpu) = irq;
+ break;
+ case IA64_IPI_RESCHEDULE:
+ sprintf(resched_name[cpu], "%s%d", action->name, cpu);
+ irq = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu,
+ action->handler, action->flags,
+ resched_name[cpu], action->dev_id);
+ per_cpu(resched_irq, cpu) = irq;
+ break;
+ case IA64_IPI_VECTOR:
+ sprintf(ipi_name[cpu], "%s%d", action->name, cpu);
+ irq = bind_ipi_to_irqhandler(IPI_VECTOR, cpu,
+ action->handler, action->flags,
+ ipi_name[cpu], action->dev_id);
+ per_cpu(ipi_irq, cpu) = irq;
+ break;
+ case IA64_CMC_VECTOR:
+ sprintf(cmc_name[cpu], "%s%d", action->name, cpu);
+ irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu,
+ action->handler,
+ action->flags,
+ cmc_name[cpu],
+ action->dev_id);
+ per_cpu(cmc_irq, cpu) = irq;
+ break;
+ case IA64_CMCP_VECTOR:
+ sprintf(cmcp_name[cpu], "%s%d", action->name, cpu);
+ irq = bind_ipi_to_irqhandler(CMCP_VECTOR, cpu,
+ action->handler,
+ action->flags,
+ cmcp_name[cpu],
+ action->dev_id);
+ per_cpu(cmcp_irq, cpu) = irq;
+ break;
+ case IA64_CPEP_VECTOR:
+ sprintf(cpep_name[cpu], "%s%d", action->name, cpu);
+ irq = bind_ipi_to_irqhandler(CPEP_VECTOR, cpu,
+ action->handler,
+ action->flags,
+ cpep_name[cpu],
+ action->dev_id);
+ per_cpu(cpep_irq, cpu) = irq;
+ break;
+ case IA64_CPE_VECTOR:
+ case IA64_MCA_RENDEZ_VECTOR:
+ case IA64_PERFMON_VECTOR:
+ case IA64_MCA_WAKEUP_VECTOR:
+ case IA64_SPURIOUS_INT_VECTOR:
+ /* No need to complain, these aren't supported. */
+ break;
+ default:
+ printk(KERN_WARNING "Percpu irq %d is unsupported "
+ "by xen!\n", vec);
+ break;
+ }
+ BUG_ON(irq < 0);
+
+ if (irq > 0) {
+ /*
+ * Mark percpu. Without this, migrate_irqs() will
+ * mark the interrupt for migrations and trigger it
+ * on cpu hotplug.
+ */
+ desc = irq_desc + irq;
+ desc->status |= IRQ_PER_CPU;
+ }
+ }
+
+ /* For BSP, we cache registered percpu irqs, and then re-walk
+ * them when initializing APs
+ */
+ if (!cpu && save) {
+ BUG_ON(saved_irq_cnt == MAX_LATE_IRQ);
+ saved_percpu_irqs[saved_irq_cnt].irq = vec;
+ saved_percpu_irqs[saved_irq_cnt].action = action;
+ saved_irq_cnt++;
+ if (!xen_slab_ready)
+ late_irq_cnt++;
+ }
+}
+
+static void
+xen_bind_early_percpu_irq(void)
+{
+ int i;
+
+ xen_slab_ready = 1;
+ /* There's no race when accessing this cached array, since only
+ * BSP will face with such step shortly
+ */
+ for (i = 0; i < late_irq_cnt; i++)
+ xen_register_percpu_irq(smp_processor_id(),
+ saved_percpu_irqs[i].irq,
+ saved_percpu_irqs[i].action, 0);
+}
+
+/* FIXME: There's no obvious point to check whether slab is ready. So
+ * a hack is used here by utilizing a late time hook.
+ */
+extern void (*late_time_init)(void);
+extern char xen_event_callback;
+extern void xen_init_IRQ(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int __devinit
+unbind_evtchn_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ if (action == CPU_DEAD) {
+ /* Unregister evtchn. */
+ if (per_cpu(cpep_irq, cpu) >= 0) {
+ unbind_from_irqhandler(per_cpu(cpep_irq, cpu), NULL);
+ per_cpu(cpep_irq, cpu) = -1;
+ }
+ if (per_cpu(cmcp_irq, cpu) >= 0) {
+ unbind_from_irqhandler(per_cpu(cmcp_irq, cpu), NULL);
+ per_cpu(cmcp_irq, cpu) = -1;
+ }
+ if (per_cpu(cmc_irq, cpu) >= 0) {
+ unbind_from_irqhandler(per_cpu(cmc_irq, cpu), NULL);
+ per_cpu(cmc_irq, cpu) = -1;
+ }
+ if (per_cpu(ipi_irq, cpu) >= 0) {
+ unbind_from_irqhandler(per_cpu(ipi_irq, cpu), NULL);
+ per_cpu(ipi_irq, cpu) = -1;
+ }
+ if (per_cpu(resched_irq, cpu) >= 0) {
+ unbind_from_irqhandler(per_cpu(resched_irq, cpu),
+ NULL);
+ per_cpu(resched_irq, cpu) = -1;
+ }
+ if (per_cpu(timer_irq, cpu) >= 0) {
+ unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL);
+ per_cpu(timer_irq, cpu) = -1;
+ }
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block unbind_evtchn_notifier = {
+ .notifier_call = unbind_evtchn_callback,
+ .priority = 0
+};
+#endif
+
+DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
+void xen_smp_intr_init_early(unsigned int cpu)
+{
+#ifdef CONFIG_SMP
+ unsigned int i;
+
+ for (i = 0; i < saved_irq_cnt; i++)
+ xen_register_percpu_irq(cpu, saved_percpu_irqs[i].irq,
+ saved_percpu_irqs[i].action, 0);
+#endif
+}
+
+void xen_smp_intr_init(void)
+{
+#ifdef CONFIG_SMP
+ unsigned int cpu = smp_processor_id();
+ struct callback_register event = {
+ .type = CALLBACKTYPE_event,
+ .address = (unsigned long)&xen_event_callback,
+ };
+
+ if (cpu == 0) {
+ /* Initialization was already done for boot cpu. */
+#ifdef CONFIG_HOTPLUG_CPU
+ /* Register the notifier only once. */
+ register_cpu_notifier(&unbind_evtchn_notifier);
+#endif
+ return;
+ }
+
+ /* This should be piggyback when setup vcpu guest context */
+ BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event));
+#endif /* CONFIG_SMP */
+}
+
+void __init
+xen_irq_init(void)
+{
+ struct callback_register event = {
+ .type = CALLBACKTYPE_event,
+ .address = (unsigned long)&xen_event_callback,
+ };
+
+ xen_init_IRQ();
+ BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event));
+ late_time_init = xen_bind_early_percpu_irq;
+}
+
+void
+xen_platform_send_ipi(int cpu, int vector, int delivery_mode, int redirect)
+{
+ int irq = -1;
+
+#ifdef CONFIG_SMP
+ /* TODO: we need to call vcpu_up here */
+ if (unlikely(vector == ap_wakeup_vector)) {
+ extern void xen_send_ipi(int cpu, int vec);
+
+ /* XXX
+ * This should be in __cpu_up(cpu) in ia64 smpboot.c
+ * like x86. But don't want to modify it,
+ * keep it untouched.
+ */
+ xen_smp_intr_init_early(cpu);
+
+ xen_send_ipi(cpu, vector);
+ /* vcpu_prepare_and_up(cpu); */
+ return;
+ }
+#endif
+
+ switch (vector) {
+ case IA64_IPI_VECTOR:
+ irq = per_cpu(ipi_to_irq, cpu)[IPI_VECTOR];
+ break;
+ case IA64_IPI_RESCHEDULE:
+ irq = per_cpu(ipi_to_irq, cpu)[RESCHEDULE_VECTOR];
+ break;
+ case IA64_CMCP_VECTOR:
+ irq = per_cpu(ipi_to_irq, cpu)[CMCP_VECTOR];
+ break;
+ case IA64_CPEP_VECTOR:
+ irq = per_cpu(ipi_to_irq, cpu)[CPEP_VECTOR];
+ break;
+ default:
+ printk(KERN_WARNING "Unsupported IPI type 0x%x\n",
+ vector);
+ irq = 0;
+ break;
+ }
+
+ BUG_ON(irq < 0);
+ notify_remote_via_irq(irq);
+ return;
+}
+#endif /* CONFIG_XEN */
+
void
register_percpu_irq (ia64_vector vec, struct irqaction *action)
{
irq_desc_t *desc;
unsigned int irq;
+#ifdef CONFIG_XEN
+ if (is_running_on_xen())
+ return xen_register_percpu_irq(smp_processor_id(),
+ vec, action, 1);
+#endif
+
irq = vec;
BUG_ON(bind_irq_vector(irq, vec, CPU_MASK_ALL));
desc = irq_desc + irq;
@@ -576,8 +925,18 @@ init_IRQ (void)
register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
#ifdef CONFIG_SMP
register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
- register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
- register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction);
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ register_percpu_irq(IA64_IPI_RESCHEDULE,
+ &xen_resched_irqaction);
+ register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH,
+ &xen_tlb_irqaction);
+ } else
+#endif
+ {
+ register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
+ register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction);
+ }
#endif
#ifdef CONFIG_PERFMON
pfm_init_percpu();
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
index 7c5242b..3fad2fe 100644
--- a/arch/ia64/xen/hypercall.S
+++ b/arch/ia64/xen/hypercall.S
@@ -123,6 +123,16 @@ END(xen_set_eflag)
#endif /* CONFIG_IA32_SUPPORT */
#endif /* ASM_SUPPORTED */
+GLOBAL_ENTRY(xen_send_ipi)
+ mov r14=r32
+ mov r15=r33
+ mov r2=0x400
+ break 0x1000
+ ;;
+ br.ret.sptk.many rp
+ ;;
+END(xen_send_ipi)
+
GLOBAL_ENTRY(__hypercall)
mov r2=r37
break 0x1000
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
index 7e6e377..357f5a8 100644
--- a/include/asm-ia64/hw_irq.h
+++ b/include/asm-ia64/hw_irq.h
@@ -15,7 +15,11 @@
#include <asm/ptrace.h>
#include <asm/smp.h>
+#ifndef CONFIG_XEN
typedef u8 ia64_vector;
+#else
+typedef u16 ia64_vector;
+#endif
/*
* 0 special
@@ -114,6 +118,12 @@ extern void destroy_and_reserve_irq (unsigned int irq);
static inline void ia64_resend_irq(unsigned int vector)
{
+#ifdef CONFIG_XEN
+ extern int resend_irq_on_evtchn(unsigned int i);
+ if (is_running_on_xen())
+ resend_irq_on_evtchn(vector);
+ else
+#endif /* CONFIG_XEN */
platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
}
diff --git a/include/asm-ia64/irq.h b/include/asm-ia64/irq.h
index a66d268..aead249 100644
--- a/include/asm-ia64/irq.h
+++ b/include/asm-ia64/irq.h
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/cpumask.h>
+#ifndef CONFIG_XEN
#define NR_VECTORS 256
#if (NR_VECTORS + 32 * NR_CPUS) < 1024
@@ -21,6 +22,38 @@
#else
#define NR_IRQS 1024
#endif
+#else
+/*
+ * The flat IRQ space is divided into two regions:
+ * 1. A one-to-one mapping of real physical IRQs. This space is only used
+ * if we have physical device-access privilege. This region is at the
+ * start of the IRQ space so that existing device drivers do not need
+ * to be modified to translate physical IRQ numbers into our IRQ space.
+ * 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
+ * are bound using the provided bind/unbind functions.
+ */
+
+#define PIRQ_BASE 0
+#define NR_PIRQS 256
+
+#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS)
+#define NR_DYNIRQS (CONFIG_NR_CPUS * 8)
+
+#define NR_IRQS (NR_PIRQS + NR_DYNIRQS)
+#define NR_IRQ_VECTORS NR_IRQS
+
+#define pirq_to_irq(_x) ((_x) + PIRQ_BASE)
+#define irq_to_pirq(_x) ((_x) - PIRQ_BASE)
+
+#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE)
+#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
+
+#define RESCHEDULE_VECTOR 0
+#define IPI_VECTOR 1
+#define CMCP_VECTOR 2
+#define CPEP_VECTOR 3
+#define NR_IPIS 4
+#endif /* CONFIG_XEN */
static __inline__ int
irq_canonicalize (int irq)
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 20/28] ia64/xen: domU xen machine vector without dma api.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (18 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 19/28] ia64/xen: xen domU irq chip introducing some helper functions, xen_send_ipi yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 21/28] ia64/xen: define xen related address conversion helper functions for domU yamahata
` (12 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0020-ia64-xen-domU-xen-machine-vector-without-dma-api.patch --]
[-- Type: text/plain, Size: 2741 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/acpi.c | 6 ++++++
arch/ia64/xen/machvec.c | 4 ++++
include/asm-ia64/machvec.h | 2 ++
include/asm-ia64/machvec_xen.h | 22 ++++++++++++++++++++++
4 files changed, 34 insertions(+), 0 deletions(-)
create mode 100644 arch/ia64/xen/machvec.c
create mode 100644 include/asm-ia64/machvec_xen.h
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 78f28d8..9c17a46 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -118,6 +118,10 @@ acpi_get_sysname(void)
return "hpzx1";
} else if (!strcmp(hdr->oem_id, "SGI")) {
return "sn2";
+#ifdef CONFIG_XEN
+ } else if (is_running_on_xen() && !strcmp(hdr->oem_id, "XEN")) {
+ return "xen";
+#endif
}
return "dig";
@@ -132,6 +136,8 @@ acpi_get_sysname(void)
return "sn2";
# elif defined (CONFIG_IA64_DIG)
return "dig";
+# elif defined (CONFIG_IA64_XEN)
+ return "xen";
# else
# error Unknown platform. Fix acpi.c.
# endif
diff --git a/arch/ia64/xen/machvec.c b/arch/ia64/xen/machvec.c
new file mode 100644
index 0000000..4ad588a
--- /dev/null
+++ b/arch/ia64/xen/machvec.c
@@ -0,0 +1,4 @@
+#define MACHVEC_PLATFORM_NAME xen
+#define MACHVEC_PLATFORM_HEADER <asm/machvec_xen.h>
+#include <asm/machvec_init.h>
+
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index c201a20..cea8d63 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -120,6 +120,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
# include <asm/machvec_hpzx1_swiotlb.h>
# elif defined (CONFIG_IA64_SGI_SN2)
# include <asm/machvec_sn2.h>
+# elif defined (CONFIG_IA64_XEN)
+# include <asm/machvec_xen.h>
# elif defined (CONFIG_IA64_GENERIC)
# ifdef MACHVEC_PLATFORM_HEADER
diff --git a/include/asm-ia64/machvec_xen.h b/include/asm-ia64/machvec_xen.h
new file mode 100644
index 0000000..ed0f84d
--- /dev/null
+++ b/include/asm-ia64/machvec_xen.h
@@ -0,0 +1,22 @@
+#ifndef _ASM_IA64_MACHVEC_XEN_h
+#define _ASM_IA64_MACHVEC_XEN_h
+
+extern ia64_mv_setup_t xen_setup;
+extern ia64_mv_cpu_init_t xen_cpu_init;
+extern ia64_mv_irq_init_t xen_irq_init;
+extern ia64_mv_send_ipi_t xen_platform_send_ipi;
+
+/*
+ * This stuff has dual use!
+ *
+ * For a generic kernel, the macros are used to initialize the
+ * platform's machvec structure. When compiling a non-generic kernel,
+ * the macros are used directly.
+ */
+#define platform_name "xen"
+#define platform_setup xen_setup
+#define platform_cpu_init xen_cpu_init
+#define platform_irq_init xen_irq_init
+#define platform_send_ipi xen_platform_send_ipi
+
+#endif /* _ASM_IA64_MACHVEC_XEN_h */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 21/28] ia64/xen: define xen related address conversion helper functions for domU
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (19 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 20/28] ia64/xen: domU xen machine vector without dma api yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 22/28] ia64/xen: mca paravirtualization yamahata
` (11 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0021-ia64-xen-define-xen-related-address-conversion-help.patch --]
[-- Type: text/plain, Size: 1483 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
include/asm-ia64/page.h | 11 +++++++++++
include/asm-ia64/xen/page.h | 19 +++++++++++++++++++
2 files changed, 30 insertions(+), 0 deletions(-)
create mode 100644 include/asm-ia64/xen/page.h
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 4999a6c..effd2af 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -227,4 +227,15 @@ get_order (unsigned long size)
(((current->personality & READ_IMPLIES_EXEC) != 0) \
? VM_EXEC : 0))
+#ifndef __ASSEMBLY__
+
+#include <linux/kernel.h>
+
+#ifdef CONFIG_XEN
+
+#include <asm/xen/page.h>
+
+#endif /* CONFIG_XEN */
+#endif /* __ASSEMBLY__ */
+
#endif /* _ASM_IA64_PAGE_H */
diff --git a/include/asm-ia64/xen/page.h b/include/asm-ia64/xen/page.h
new file mode 100644
index 0000000..9ab8148
--- /dev/null
+++ b/include/asm-ia64/xen/page.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_IA64_MADDR_H
+#define _ASM_IA64_MADDR_H
+
+#include <linux/kernel.h>
+#include <asm/xen/hypervisor.h>
+#include <asm/xen/hypercall.h>
+#include <xen/features.h>
+#include <xen/interface/xen.h>
+
+#define mfn_to_pfn(mfn) (mfn)
+#define pfn_to_mfn(pfn) (pfn)
+
+#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT))
+#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT)
+#define virt_to_machine(virt) __pa(virt) /* for tpmfront.c */
+
+#define set_phys_to_machine(pfn, mfn) do { } while (0)
+
+#endif /* _ASM_IA64_MADDR_H */
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 22/28] ia64/xen: mca paravirtualization
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (20 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 21/28] ia64/xen: define xen related address conversion helper functions for domU yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 23/28] ia64/xen: sal paravirtualization yamahata
` (10 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0022-ia64-xen-mca-paravirtualization.patch --]
[-- Type: text/plain, Size: 1737 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/mca.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 6e17aed..94f1023 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -339,11 +339,33 @@ typedef struct ia64_state_log_s
static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES];
+#ifdef CONFIG_XEN
+DEFINE_SPINLOCK(ia64_mca_xencomm_lock);
+LIST_HEAD(ia64_mca_xencomm_list);
+
+#define IA64_MCA_XENCOMM_ALLOCATE(rec, desc) \
+ if (is_running_on_xen()) { \
+ ia64_mca_xencomm_t *entry; \
+ entry = alloc_bootmem(sizeof(ia64_mca_xencomm_t)); \
+ entry->record = rec; \
+ entry->handle = desc; \
+ list_add(&entry->list, &ia64_mca_xencomm_list); \
+ }
+#define IA64_LOG_ALLOCATE(it, size) \
+ {ia64_err_rec_t *rec; \
+ ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = rec = \
+ (ia64_err_rec_t *)alloc_bootmem(size); \
+ IA64_MCA_XENCOMM_ALLOCATE(rec, xencomm_map(rec, size)); \
+ ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = rec = \
+ (ia64_err_rec_t *)alloc_bootmem(size); \
+ IA64_MCA_XENCOMM_ALLOCATE(rec, xencomm_map(rec, size));}
+#else
#define IA64_LOG_ALLOCATE(it, size) \
{ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \
(ia64_err_rec_t *)alloc_bootmem(size); \
ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \
(ia64_err_rec_t *)alloc_bootmem(size);}
+#endif
#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock)
#define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s)
#define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s)
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 23/28] ia64/xen: sal paravirtualization.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (21 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 22/28] ia64/xen: mca paravirtualization yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 24/28] ia64/xen: time paravirtualization yamahata
` (9 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0023-ia64-xen-sal-paravirtualization.patch --]
[-- Type: text/plain, Size: 3699 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/salinfo.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
include/asm-ia64/sal.h | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 779c3cc..91bc631 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -378,6 +378,25 @@ salinfo_log_open(struct inode *inode, struct file *file)
data->open = 0;
return -ENOMEM;
}
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ ia64_mca_xencomm_t *entry;
+ unsigned long flags;
+
+ entry = vmalloc(sizeof(ia64_mca_xencomm_t));
+ if (!entry) {
+ data->open = 0;
+ vfree(data->log_buffer);
+ return -ENOMEM;
+ }
+ entry->record = data->log_buffer;
+ entry->handle = xencomm_map(data->log_buffer,
+ ia64_sal_get_state_info_size(data->type));
+ spin_lock_irqsave(&ia64_mca_xencomm_lock, flags);
+ list_add(&entry->list, &ia64_mca_xencomm_list);
+ spin_unlock_irqrestore(&ia64_mca_xencomm_lock, flags);
+ }
+#endif
return 0;
}
@@ -389,6 +408,31 @@ salinfo_log_release(struct inode *inode, struct file *file)
struct salinfo_data *data = entry->data;
if (data->state == STATE_NO_DATA) {
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ struct list_head *pos, *n;
+ ia64_mca_xencomm_t *found_entry = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ia64_mca_xencomm_lock, flags);
+ list_for_each_safe(pos, n, &ia64_mca_xencomm_list) {
+ ia64_mca_xencomm_t *entry;
+
+ entry = list_entry(pos, ia64_mca_xencomm_t,
+ list);
+ if (entry->record == data->log_buffer) {
+ list_del(&entry->list);
+ found_entry = entry;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&ia64_mca_xencomm_lock, flags);
+ if (found_entry) {
+ xencomm_free(found_entry->handle);
+ vfree(found_entry);
+ }
+ }
+#endif
vfree(data->log_buffer);
vfree(data->oemdata);
data->log_buffer = NULL;
diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
index 2251118..3c20a58 100644
--- a/include/asm-ia64/sal.h
+++ b/include/asm-ia64/sal.h
@@ -42,6 +42,9 @@
#include <asm/pal.h>
#include <asm/system.h>
#include <asm/fpu.h>
+#ifdef CONFIG_XEN
+#include <asm/xen/xencomm.h>
+#endif
extern spinlock_t sal_lock;
@@ -679,10 +682,43 @@ ia64_sal_clear_state_info (u64 sal_info_type)
/* Get the processor and platform information logged by SAL with respect to the machine
* state at the time of the MCAs, INITs, CMCs, or CPEs.
*/
+#ifdef CONFIG_XEN
+static inline u64 ia64_sal_get_state_info_size (u64 sal_info_type);
+typedef struct ia64_mca_xencomm_t {
+ void *record;
+ struct xencomm_handle *handle;
+ struct list_head list;
+} ia64_mca_xencomm_t;
+extern struct list_head ia64_mca_xencomm_list;
+extern spinlock_t ia64_mca_xencomm_lock;
+#endif
+
static inline u64
ia64_sal_get_state_info (u64 sal_info_type, u64 *sal_info)
{
struct ia64_sal_retval isrv;
+#ifdef CONFIG_XEN
+ if (is_running_on_xen()) {
+ ia64_mca_xencomm_t *entry;
+ struct xencomm_handle *desc = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ia64_mca_xencomm_lock, flags);
+ list_for_each_entry(entry, &ia64_mca_xencomm_list, list) {
+ if (entry->record == sal_info) {
+ desc = entry->handle;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&ia64_mca_xencomm_lock, flags);
+
+ if (desc == NULL)
+ return 0;
+
+ SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO, sal_info_type, 0,
+ desc, 0, 0, 0, 0);
+ } else
+#endif
SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO, sal_info_type, 0,
sal_info, 0, 0, 0, 0);
if (isrv.status)
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 24/28] ia64/xen: time paravirtualization
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (22 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 23/28] ia64/xen: sal paravirtualization yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 25/28] ia64/xen: gate page paravirtualization yamahata
` (8 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0024-ia64-xen-time-paravirtualization.patch --]
[-- Type: text/plain, Size: 7293 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/time.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 204 insertions(+), 0 deletions(-)
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 17fda52..1bb0362 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -29,6 +29,14 @@
#include <asm/sections.h>
#include <asm/system.h>
+#include <asm/xen/hypervisor.h>
+#ifdef CONFIG_XEN
+#include <linux/kernel_stat.h>
+#include <linux/posix-timers.h>
+#include <xen/interface/vcpu.h>
+#include <asm/percpu.h>
+#endif
+
#include "fsyscall_gtod_data.h"
static cycle_t itc_get_cycles(void);
@@ -38,6 +46,17 @@ struct fsyscall_gtod_data_t fsyscall_gtod_data = {
};
struct itc_jitter_data_t itc_jitter_data;
+#ifdef CONFIG_XEN
+static void itc_jitter_data_reset(void)
+{
+ u64 lcycle, ret;
+
+ do {
+ lcycle = itc_jitter_data.itc_lastcycle;
+ ret = cmpxchg(&itc_jitter_data.itc_lastcycle, lcycle, 0);
+ } while (unlikely(ret != lcycle));
+}
+#endif
volatile int time_keeper_id = 0; /* smp_processor_id() of time-keeper */
@@ -56,13 +75,105 @@ static struct clocksource clocksource_itc = {
.mult = 0, /*to be calculated*/
.shift = 16,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+#ifdef CONFIG_XEN
+ .resume = itc_jitter_data_reset,
+#endif
};
static struct clocksource *itc_clocksource;
+#ifdef CONFIG_XEN
+DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
+DEFINE_PER_CPU(unsigned long, processed_stolen_time);
+DEFINE_PER_CPU(unsigned long, processed_blocked_time);
+#define NS_PER_TICK (1000000000LL/HZ)
+static unsigned long
+consider_steal_time(unsigned long new_itm)
+{
+ unsigned long stolen, blocked, sched_time;
+ unsigned long delta_itm = 0, stolentick = 0;
+ int cpu = smp_processor_id();
+ struct vcpu_runstate_info *runstate;
+ struct task_struct *p = current;
+
+ runstate = &per_cpu(runstate, smp_processor_id());
+
+ do {
+ sched_time = runstate->state_entry_time;
+ mb();
+ stolen = runstate->time[RUNSTATE_runnable] +
+ runstate->time[RUNSTATE_offline] -
+ per_cpu(processed_stolen_time, cpu);
+ blocked = runstate->time[RUNSTATE_blocked] -
+ per_cpu(processed_blocked_time, cpu);
+ mb();
+ } while (sched_time != runstate->state_entry_time);
+
+ /*
+ * Check for vcpu migration effect
+ * In this case, itc value is reversed.
+ * This causes huge stolen value.
+ * This function just checks and reject this effect.
+ */
+ if (!time_after_eq(runstate->time[RUNSTATE_blocked],
+ per_cpu(processed_blocked_time, cpu)))
+ blocked = 0;
+
+ if (!time_after_eq(runstate->time[RUNSTATE_runnable] +
+ runstate->time[RUNSTATE_offline],
+ per_cpu(processed_stolen_time, cpu)))
+ stolen = 0;
+
+ if (!time_after(delta_itm + new_itm, ia64_get_itc()))
+ stolentick = ia64_get_itc() - delta_itm - new_itm;
+
+ do_div(stolentick, NS_PER_TICK);
+ stolentick++;
+
+ do_div(stolen, NS_PER_TICK);
+
+ if (stolen > stolentick)
+ stolen = stolentick;
+
+ stolentick -= stolen;
+ do_div(blocked, NS_PER_TICK);
+
+ if (blocked > stolentick)
+ blocked = stolentick;
+
+ if (stolen > 0 || blocked > 0) {
+ account_steal_time(NULL, jiffies_to_cputime(stolen));
+ account_steal_time(idle_task(cpu), jiffies_to_cputime(blocked));
+ run_local_timers();
+
+ if (rcu_pending(cpu))
+ rcu_check_callbacks(cpu, user_mode(get_irq_regs()));
+
+ scheduler_tick();
+ run_posix_cpu_timers(p);
+ delta_itm += local_cpu_data->itm_delta * (stolen + blocked);
+
+ if (cpu == time_keeper_id) {
+ write_seqlock(&xtime_lock);
+ do_timer(stolen + blocked);
+ local_cpu_data->itm_next = delta_itm + new_itm;
+ write_sequnlock(&xtime_lock);
+ } else {
+ local_cpu_data->itm_next = delta_itm + new_itm;
+ }
+ per_cpu(processed_stolen_time, cpu) += NS_PER_TICK * stolen;
+ per_cpu(processed_blocked_time, cpu) += NS_PER_TICK * blocked;
+ }
+ return delta_itm;
+}
+#else
+#define consider_steal_time(new_itm) (0)
+#endif
+
static irqreturn_t
timer_interrupt (int irq, void *dev_id)
{
unsigned long new_itm;
+ unsigned long delta_itm; /* XEN */
if (unlikely(cpu_is_offline(smp_processor_id()))) {
return IRQ_HANDLED;
@@ -78,6 +189,13 @@ timer_interrupt (int irq, void *dev_id)
profile_tick(CPU_PROFILING);
+ if (is_running_on_xen()) {
+ delta_itm = consider_steal_time(new_itm);
+ new_itm += delta_itm;
+ if (time_after(new_itm, ia64_get_itc()) && delta_itm)
+ goto skip_process_time_accounting;
+ }
+
while (1) {
update_process_times(user_mode(get_irq_regs()));
@@ -107,6 +225,8 @@ timer_interrupt (int irq, void *dev_id)
local_irq_disable();
}
+skip_process_time_accounting: /* XEN */
+
do {
/*
* If we're too close to the next clock tick for
@@ -161,6 +281,84 @@ static int __init nojitter_setup(char *str)
__setup("nojitter", nojitter_setup);
+#ifdef CONFIG_XEN
+/* taken from i386/kernel/time-xen.c */
+static void init_missing_ticks_accounting(int cpu)
+{
+ struct vcpu_register_runstate_memory_area area;
+ struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu);
+ int rc;
+
+ memset(runstate, 0, sizeof(*runstate));
+
+ area.addr.v = runstate;
+ rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu,
+ &area);
+ WARN_ON(rc && rc != -ENOSYS);
+
+ per_cpu(processed_blocked_time, cpu) = runstate->time[RUNSTATE_blocked];
+ per_cpu(processed_stolen_time, cpu) = runstate->time[RUNSTATE_runnable]
+ + runstate->time[RUNSTATE_offline];
+}
+
+static int xen_ia64_settimefoday_after_resume;
+
+static int __init __xen_ia64_settimeofday_after_resume(char *str)
+{
+ xen_ia64_settimefoday_after_resume = 1;
+ return 1;
+}
+
+__setup("xen_ia64_settimefoday_after_resume",
+ __xen_ia64_settimeofday_after_resume);
+
+/* Called after suspend, to resume time. */
+void
+time_resume(void)
+{
+ unsigned int cpu;
+
+ /* Just trigger a tick. */
+ ia64_cpu_local_tick();
+
+ if (xen_ia64_settimefoday_after_resume) {
+ /* do_settimeofday() resets timer interplator */
+ struct timespec xen_time;
+ int ret;
+ efi_gettimeofday(&xen_time);
+
+ ret = do_settimeofday(&xen_time);
+ WARN_ON(ret);
+ } else {
+#if 0
+ /* adjust EFI time */
+ struct timespec my_time = CURRENT_TIME;
+ struct timespec xen_time;
+ static timespec diff;
+ struct xen_domctl domctl;
+ int ret;
+
+ efi_gettimeofday(&xen_time);
+ diff = timespec_sub(&xen_time, &my_time);
+ domctl.cmd = XEN_DOMCTL_settimeoffset;
+ domctl.domain = DOMID_SELF;
+ domctl.u.settimeoffset.timeoffset_seconds = diff.tv_sec;
+ ret = HYPERVISOR_domctl_op(&domctl);
+ WARN_ON(ret);
+#endif
+ /* itc_clocksource remembers the last timer status in
+ * itc_jitter_data. Forget it */
+ clocksource_resume();
+ }
+
+ for_each_online_cpu(cpu)
+ init_missing_ticks_accounting(cpu);
+
+ touch_softlockup_watchdog();
+}
+#else
+#define init_missing_ticks_accounting(cpu) do {} while (0)
+#endif
void __devinit
ia64_init_itm (void)
@@ -256,6 +454,12 @@ ia64_init_itm (void)
*/
clocksource_itc.rating = 50;
+ if (is_running_on_xen())
+ init_missing_ticks_accounting(smp_processor_id());
+
+ /* avoid softlock up message when cpu is unplug and plugged again. */
+ touch_softlockup_watchdog();
+
/* Setup the CPU local timer tick */
ia64_cpu_local_tick();
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 25/28] ia64/xen: gate page paravirtualization
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (23 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 24/28] ia64/xen: time paravirtualization yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 26/28] ia64/xen: fsys paravirtualization yamahata
` (7 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0025-ia64-xen-gate-page-paravirtualization.patch --]
[-- Type: text/plain, Size: 9814 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/Makefile | 58 +++++++++++++++++++++++++++++++++++++++
arch/ia64/kernel/gate.S | 55 +++++++++++++++++++++++++++++++++++++
arch/ia64/kernel/gate.lds.S | 18 ++++++++++++
arch/ia64/kernel/patch.c | 28 +++++++++++++++++++
arch/ia64/kernel/vmlinux.lds.S | 6 ++++
arch/ia64/kernel/xengate-data.S | 3 ++
arch/ia64/mm/init.c | 22 +++++++++++++-
7 files changed, 188 insertions(+), 2 deletions(-)
create mode 100644 arch/ia64/kernel/xengate-data.S
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index d0e22bb..661619c 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -75,3 +75,61 @@ $(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE
# We must build gate.so before we can assemble it.
# Note: kbuild does not track this dependency due to usage of .incbin
$(obj)/gate-data.o: $(obj)/gate.so
+
+#
+# gate page paravirtualization for xen
+#
+obj-$(CONFIG_XEN) += xengate-data.o
+
+ifeq ($(CONFIG_XEN), y)
+# The gate DSO image is built using a special linker script.
+targets += xengate.so xengate-syms.o
+endif
+
+extra-$(CONFIG_XEN) += xengate.so xengate.lds xengate.o
+
+AFLAGS_xengate.o += -D__XEN_IA64_VDSO_PARAVIRT
+$(obj)/xengate.o: $(src)/gate.S FORCE
+ $(call if_changed_dep,as_o_S)
+
+CPPFLAGS_xengate.lds := -P -C -U$(ARCH) -D__XEN_IA64_VDSO_PARAVIRT
+$(obj)/xengate.lds: $(src)/gate.lds.S
+ $(call if_changed_dep,cpp_lds_S)
+
+GATECFLAGS_xengate.so = -shared -s -Wl,-soname=linux-gate.so.1 \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv)
+$(obj)/xengate.so: $(obj)/xengate.lds $(obj)/xengate.o FORCE
+ $(call if_changed,gate)
+
+ifeq ($(CONFIG_XEN), y)
+$(obj)/built-in.o: $(obj)/xengate-syms.o
+$(obj)/built-in.o: ld_flags += -R $(obj)/xengate-syms.o
+$(obj)/mca_recovery.o: $(obj)/gate-syms.o $(obj)/xengate-syms.o
+endif
+
+GATECFLAGS_xengate-syms.o = -r
+$(obj)/xengate-syms.o: $(obj)/xengate.lds $(obj)/xengate.o FORCE
+ $(call if_changed,gate)
+$(obj)/xengate-data.o: $(obj)/xengate.so
+
+#
+# .tmp_gate.o to calculate padding size for __kernel_syscall_via_epc
+#
+extra-$(CONFIG_XEN) += gate-skip.s .tmp_gate.o
+
+ifeq ($(CONFIG_XEN), y)
+AFLAGS_gate.o += -D__KERNEL_SYSCALL_VIA_EPC_PADDING
+$(obj)/gate.o: $(obj)/gate-skip.s FORCE
+endif
+
+$(obj)/.tmp_gate.o: $(src)/gate.S FORCE
+ $(call if_changed_dep,as_o_S)
+
+quiet_cmd_gate_size = GATE_SIZE $@
+ cmd_gate_size = $(NM) --extern-only --print-size $(obj)/xengate.o | \
+ $(AWK) '/__kernel_syscall_via_epc/{printf "\t.skip 0x"$$2" - "}' > $@; \
+ $(NM) --extern-only --print-size $(obj)/.tmp_gate.o | \
+ $(AWK) '/__kernel_syscall_via_epc/{printf "0x"$$2"\n"}' >> $@
+
+$(obj)/gate-skip.s: $(obj)/xengate.o $(obj)/.tmp_gate.o FORCE
+ $(call if_changed,gate_size)
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
index 74b1ccc..7c62417 100644
--- a/arch/ia64/kernel/gate.S
+++ b/arch/ia64/kernel/gate.S
@@ -77,15 +77,40 @@ GLOBAL_ENTRY(__kernel_syscall_via_epc)
epc // B causes split-issue
}
;;
+#ifdef __XEN_IA64_VDSO_PARAVIRT
+ // r20 = 1
+ // r22 = &vcpu->vcpu_info->evtchn_upcall_mask
+ // r24 = &vcpu->vcpu_info->evtchn_upcall_pending
+ // r25 = tmp
+ // r31 = tmp
+ // p11 = tmp
+ // p14 = tmp
+ mov r20=1
+ movl r22=XSI_PSR_I_ADDR
+ ;;
+ ld8 r22=[r22]
+ ;;
+ st1 [r22]=r20
+ rum psr.be
+ adds r24=-1,r22
+#else
rsm psr.be | psr.i // M2 (5 cyc to srlz.d)
+#endif
LOAD_FSYSCALL_TABLE(r14) // X
;;
mov r16=IA64_KR(CURRENT) // M2 (12 cyc)
shladd r18=r17,3,r14 // A
mov r19=NR_syscalls-1 // A
+#ifdef __XEN_IA64_VDSO_PARAVIRT
+ XEN_HYPER_GET_PSR
+ ;;
+ lfetch [r18] // M0|1
+ mov r29=r8
+#else
;;
lfetch [r18] // M0|1
mov r29=psr // M2 (12 cyc)
+#endif
// If r17 is a NaT, p6 will be zero
cmp.geu p6,p7=r19,r17 // A (sysnr > 0 && sysnr < 1024+NR_syscalls)?
;;
@@ -99,9 +124,27 @@ GLOBAL_ENTRY(__kernel_syscall_via_epc)
;;
nop.m 0
(p6) tbit.z.unc p8,p0=r18,0 // I0 (dual-issues with "mov b7=r18"!)
+#ifdef __XEN_IA64_VDSO_PARAVIRT
+
+#define XEN_SET_PSR_I(pred) \
+(pred) ld1 r31=[r22]; \
+ ;; ; \
+(pred) st1 [r22]=r0; \
+(pred) cmp.ne.unc p14,p0=r0,r31; \
+ ;; ; \
+(p14) ld1 r25=[r24]; \
+ ;; ; \
+(p14) cmp.ne.unc p11,p0=r0,r25; \
+ ;; ; \
+(p11) XEN_HYPER_SSM_I;
+
+ ;;
+ XEN_SET_PSR_I(p8)
+#else
nop.i 0
;;
(p8) ssm psr.i
+#endif
(p6) mov b7=r18 // I0
(p8) br.dptk.many b7 // B
@@ -122,11 +165,23 @@ GLOBAL_ENTRY(__kernel_syscall_via_epc)
#else
BRL_COND_FSYS_BUBBLE_DOWN(p6)
#endif
+#ifdef __XEN_IA64_VDSO_PARAVIRT
+ XEN_SET_PSR_I(p0)
+#else
ssm psr.i
+#endif
mov r10=-1
(p10) mov r8=EINVAL
(p9) mov r8=ENOSYS
FSYS_RETURN
+#ifdef __KERNEL_SYSCALL_VIA_EPC_PADDING
+ /*
+ * All values/sizes of __kernel_xxx symbol in gate.so and xengate.so
+ * must be same to each other.
+ * Adjust symbol size in gate.so to be same to the one in xengate.so.
+ */
+.include "arch/ia64/kernel/gate-skip.s"
+#endif
END(__kernel_syscall_via_epc)
# define ARG0_OFF (16 + IA64_SIGFRAME_ARG0_OFFSET)
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S
index 3cb1abc..b9615cf 100644
--- a/arch/ia64/kernel/gate.lds.S
+++ b/arch/ia64/kernel/gate.lds.S
@@ -33,6 +33,24 @@ SECTIONS
. = GATE_ADDR + 0x600;
.data.patch : {
+#ifdef __XEN_IA64_VDSO_PARAVIRT
+#define __start_gate_mckinley_e9_patchlist \
+ __start_gate_mckinley_e9_patchlist_xen
+#define __end_gate_mckinley_e9_patchlist \
+ __end_gate_mckinley_e9_patchlist_xen
+#define __start_gate_vtop_patchlist \
+ __start_gate_vtop_patchlist_xen
+#define __end_gate_vtop_patchlist \
+ __end_gate_vtop_patchlist_xen
+#define __start_gate_fsyscall_patchlist \
+ __start_gate_fsyscall_patchlist_xen
+#define __end_gate_fsyscall_patchlist \
+ __end_gate_fsyscall_patchlist_xen
+#define __start_gate_brl_fsys_bubble_down_patchlist \
+ __start_gate_brl_fsys_bubble_down_patchlist_xen
+#define __end_gate_brl_fsys_bubble_down_patchlist \
+ __end_gate_brl_fsys_bubble_down_patchlist_xen
+#endif
__start_gate_mckinley_e9_patchlist = .;
*(.data.patch.mckinley_e9)
__end_gate_mckinley_e9_patchlist = .;
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
index 2cb9425..4676ac4 100644
--- a/arch/ia64/kernel/patch.c
+++ b/arch/ia64/kernel/patch.c
@@ -181,9 +181,37 @@ patch_brl_fsys_bubble_down (unsigned long start, unsigned long end)
ia64_srlz_i();
}
+#ifdef CONFIG_XEN
+void __init
+ia64_patch_gate_xen (void)
+{
+ extern char __start_gate_mckinley_e9_patchlist_xen[], __end_gate_mckinley_e9_patchlist_xen[];
+ extern char __start_gate_vtop_patchlist_xen[], __end_gate_vtop_patchlist_xen[];
+ extern char __start_gate_fsyscall_patchlist_xen[], __end_gate_fsyscall_patchlist_xen[];
+ extern char __start_gate_brl_fsys_bubble_down_patchlist_xen[], __end_gate_brl_fsys_bubble_down_patchlist_xen[];
+# define START(name) ((unsigned long) __start_gate_##name##_patchlist_xen)
+# define END(name) ((unsigned long)__end_gate_##name##_patchlist_xen)
+
+ patch_fsyscall_table(START(fsyscall), END(fsyscall));
+ patch_brl_fsys_bubble_down(START(brl_fsys_bubble_down), END(brl_fsys_bubble_down));
+ ia64_patch_vtop(START(vtop), END(vtop));
+ ia64_patch_mckinley_e9(START(mckinley_e9), END(mckinley_e9));
+
+# undef START
+# undef END
+}
+#else
+#define ia64_patch_gate_xen() do { } while (0)
+#endif
+
void __init
ia64_patch_gate (void)
{
+ if (is_running_on_xen()) {
+ ia64_patch_gate_xen();
+ return;
+ }
+
# define START(name) ((unsigned long) __start_gate_##name##_patchlist)
# define END(name) ((unsigned long)__end_gate_##name##_patchlist)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 0cbe0a1..0cedc30 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -230,6 +230,12 @@ SECTIONS
__start_gate_section = .;
*(.data.gate)
__stop_gate_section = .;
+#if defined(CONFIG_XEN)
+ . = ALIGN(PAGE_SIZE);
+ __start_xen_gate_section = .;
+ *(.data.gate.xen)
+ __stop_xen_gate_section = .;
+#endif
}
. = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose
* kernel data
diff --git a/arch/ia64/kernel/xengate-data.S b/arch/ia64/kernel/xengate-data.S
new file mode 100644
index 0000000..122bb5f
--- /dev/null
+++ b/arch/ia64/kernel/xengate-data.S
@@ -0,0 +1,3 @@
+ .section .data.gate.xen, "aw"
+
+ .incbin "arch/ia64/kernel/xengate.so"
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 25aef62..5e327ac 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -267,16 +267,34 @@ static void __init
setup_gate (void)
{
struct page *page;
+ void *gate_page_addr = __start_gate_section;
+
+#ifdef CONFIG_XEN
+ unsigned long unused_gate;
+ extern char __start_xen_gate_section[];
+ if (is_running_on_xen()) {
+ gate_page_addr = __start_xen_gate_section;
+ unused_gate = (unsigned long)ia64_imva(__start_gate_section);
+ } else
+ unused_gate =
+ (unsigned long)ia64_imva(__start_xen_gate_section);
+#ifndef HAVE_BUGGY_SEGREL
+ ClearPageReserved(virt_to_page(unused_gate));
+ init_page_count(virt_to_page(unused_gate));
+ free_page(unused_gate);
+ ++totalram_pages;
+#endif
+#endif
/*
* Map the gate page twice: once read-only to export the ELF
* headers etc. and once execute-only page to enable
* privilege-promotion via "epc":
*/
- page = virt_to_page(ia64_imva(__start_gate_section));
+ page = virt_to_page(ia64_imva(gate_page_addr));
put_kernel_page(page, GATE_ADDR, PAGE_READONLY);
#ifdef HAVE_BUGGY_SEGREL
- page = virt_to_page(ia64_imva(__start_gate_section + PAGE_SIZE));
+ page = virt_to_page(ia64_imva(gate_page_addr + PAGE_SIZE));
put_kernel_page(page, GATE_ADDR + PAGE_SIZE, PAGE_GATE);
#else
put_kernel_page(page, GATE_ADDR + PERCPU_PAGE_SIZE, PAGE_GATE);
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 26/28] ia64/xen: fsys paravirtualization.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (24 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 25/28] ia64/xen: gate page paravirtualization yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 27/28] ia64/xen: update Kconfig to allow xen domU Linux yamahata
` (6 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0026-ia64-xen-fsys-paravirtualization.patch --]
[-- Type: text/plain, Size: 1885 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/fsys.S | 41 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 4484197..7d97e37 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -570,11 +570,34 @@ ENTRY(fsys_fallback_syscall)
adds r17=-1024,r15
movl r14=sys_call_table
;;
+#ifdef CONFIG_XEN
+ movl r18=running_on_xen;;
+ ld4 r18=[r18];;
+ // p14 = running_on_xen
+ // p15 = !running_on_xen
+ cmp.ne p14,p15=r0,r18
+ ;;
+(p14) movl r18=XSI_PSR_I_ADDR;;
+(p14) ld8 r18=[r18]
+(p14) mov r29=1;;
+(p14) st1 [r18]=r29
+(p15) rsm psr.i
+#else
rsm psr.i
+#endif
shladd r18=r17,3,r14
;;
ld8 r18=[r18] // load normal (heavy-weight) syscall entry-point
+#ifdef CONFIG_XEN
+(p14) mov r27=r8
+(p14) XEN_HYPER_GET_PSR
+ ;;
+(p14) mov r29=r8
+(p14) mov r8=r27
+(p15) mov r29=psr // read psr (12 cyc load latency)
+#else
mov r29=psr // read psr (12 cyc load latency)
+#endif
mov r27=ar.rsc
mov r21=ar.fpsr
mov r26=ar.pfs
@@ -686,7 +709,25 @@ GLOBAL_ENTRY(fsys_bubble_down)
mov rp=r14 // I0 set the real return addr
and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A
;;
+#ifdef CONFIG_XEN
+ movl r14=running_on_xen;;
+ ld4 r14=[r14];;
+ // p14 = running_on_xen
+ // p15 = !running_on_xen
+ cmp.ne p14,p15=r0,r14
+ ;;
+(p14) movl r28=XSI_PSR_I_ADDR;;
+(p14) ld8 r28=[r28];;
+(p14) adds r28=-1,r28;; // event_pending
+(p14) ld1 r14=[r28];;
+(p14) cmp.ne.unc p13,p14=r14,r0;;
+(p13) XEN_HYPER_SSM_I
+(p14) adds r28=1,r28;; // event_mask
+(p14) st1 [r28]=r0;;
+(p15) ssm psr.i
+#else
ssm psr.i // M2 we're on kernel stacks now, reenable irqs
+#endif
cmp.eq p8,p0=r3,r0 // A
(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 27/28] ia64/xen: update Kconfig to allow xen domU Linux
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (25 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 26/28] ia64/xen: fsys paravirtualization yamahata
@ 2008-02-21 9:17 ` yamahata
2008-02-21 9:17 ` [PATCH 28/28] ia64/xen: add ia64/xen domU config yamahata
` (5 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0027-ia64-xen-update-Kconfig-to-allow-xen-domU-Linux.patch --]
[-- Type: text/plain, Size: 1448 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/Kconfig | 6 +++++-
arch/ia64/xen/Kconfig | 29 +++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletions(-)
create mode 100644 arch/ia64/xen/Kconfig
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index bc84008..31313bc 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -178,7 +178,7 @@ config PARAVIRT_NOP_B_PATCH
"br.cond.sptk.many <native_xxx>" and replace it with 'nop.b 0'
when running on xen.
-#source "arch/ia64/xen/Kconfig"
+source "arch/ia64/xen/Kconfig"
endif
@@ -238,6 +238,10 @@ config IA64_HP_SIM
bool "Ski-simulator"
select SWIOTLB
+config IA64_XEN
+ bool "Xen guest"
+ depends on XEN
+
endchoice
choice
diff --git a/arch/ia64/xen/Kconfig b/arch/ia64/xen/Kconfig
new file mode 100644
index 0000000..30f54c3
--- /dev/null
+++ b/arch/ia64/xen/Kconfig
@@ -0,0 +1,29 @@
+#
+# This Kconfig describes xen/ia64 options
+#
+
+config XEN
+ bool "Xen hypervisor support"
+ default y
+ select PARAVIRT
+ select PARAVIRT_ALT
+ select PARAVIRT_ENTRY
+ select PARAVIRT_NOP_B_PATCH
+ select XEN_XENCOMM
+ select IA64_XEN
+ help
+ Enable Xen hypervisor support. Resulting kernel runs
+ both as a guest OS on Xen and natively on hardware.
+
+if XEN
+config XEN_INTERFACE_VERSION
+ hex
+ default 0x00030207
+
+config XEN_XENCOMM
+ def_bool y
+
+config NO_IDLE_HZ
+ def_bool y
+
+endif
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 28/28] ia64/xen: add ia64/xen domU config.
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
` (26 preceding siblings ...)
2008-02-21 9:17 ` [PATCH 27/28] ia64/xen: update Kconfig to allow xen domU Linux yamahata
@ 2008-02-21 9:17 ` yamahata
[not found] ` <20080221091904.811793000@ls.local.valinux.co.jp>
` (4 subsequent siblings)
32 siblings, 0 replies; 45+ messages in thread
From: yamahata @ 2008-02-21 9:17 UTC (permalink / raw)
To: linux-ia64; +Cc: xen-ia64-devel, kvm-ia64-devel, virtualization
[-- Attachment #1: 0028-ia64-xen-add-ia64-xen-domU-config.patch --]
[-- Type: text/plain, Size: 21527 bytes --]
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/configs/xen_domu_wip_defconfig | 854 ++++++++++++++++++++++++++++++
1 files changed, 854 insertions(+), 0 deletions(-)
create mode 100644 arch/ia64/configs/xen_domu_wip_defconfig
diff --git a/arch/ia64/configs/xen_domu_wip_defconfig b/arch/ia64/configs/xen_domu_wip_defconfig
new file mode 100644
index 0000000..f6f6171
--- /dev/null
+++ b/arch/ia64/configs/xen_domu_wip_defconfig
@@ -0,0 +1,854 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.25-rc1
+# Thu Feb 14 10:38:56 2008
+#
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="xen-ia64"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=20
+# CONFIG_CGROUPS is not set
+# CONFIG_FAIR_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_ZONE_DMA=y
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_SWIOTLB=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_DMI=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_PARAVIRT_GUEST=y
+CONFIG_PARAVIRT=y
+CONFIG_PARAVIRT_ALT=y
+CONFIG_PARAVIRT_ENTRY=y
+CONFIG_PARAVIRT_NOP_B_PATCH=y
+CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030207
+CONFIG_XEN_PRIVILEGED_GUEST=y
+# CONFIG_XEN_IA64_EXPOSE_P2M is not set
+CONFIG_XEN_XENCOMM=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_IA64_XEN is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_PGTABLE_3=y
+# CONFIG_PGTABLE_4 is not set
+CONFIG_HZ=100
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_IA64_L1_CACHE_SHIFT=7
+# CONFIG_IA64_CYCLONE is not set
+CONFIG_IOSAPIC=y
+# CONFIG_IA64_SGI_SN_XP is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PERMIT_BSP_REMOVE is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_MIGRATION is not set
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_NR_QUICK=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=10
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_HOLES_IN_ZONE=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y
+# CONFIG_IA32_SUPPORT is not set
+# CONFIG_COMPAT_FOR_U64_ALIGNMENT is not set
+CONFIG_IA64_MCA_RECOVERY=y
+# CONFIG_PERFMON is not set
+CONFIG_IA64_PALINFO=y
+# CONFIG_IA64_MC_ERR_INJECT is not set
+CONFIG_SGI_SN=y
+# CONFIG_IA64_ESI is not set
+# CONFIG_IA64_HP_AML_NFW is not set
+
+#
+# SN Devices
+#
+# CONFIG_SGI_IOC3 is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+# CONFIG_DMIID is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+CONFIG_ACPI=y
+# CONFIG_ACPI_PROCFS is not set
+# CONFIG_ACPI_PROCFS_POWER is not set
+# CONFIG_ACPI_SYSFS_POWER is not set
+# CONFIG_ACPI_PROC_EVENT is not set
+# CONFIG_ACPI_BUTTON is not set
+# CONFIG_ACPI_FAN is not set
+# CONFIG_ACPI_DOCK is not set
+# CONFIG_ACPI_PROCESSOR is not set
+CONFIG_ACPI_NUMA=y
+# CONFIG_ACPI_CUSTOM_DSDT_INITRD is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_EC=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_CONTAINER is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_ADVANCED is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=y
+# CONFIG_VETH is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_ARCNET is not set
+# CONFIG_NET_ETHERNET is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_WAN is not set
+CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_SGI_SNSC is not set
+# CONFIG_SGI_TIOCX is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SGI_L1_CONSOLE is not set
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_XEN=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_MMTIMER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
+
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+# CONFIG_MSPEC is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
+
+#
+# HP Simulator drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+CONFIG_IA64_PRINT_HAZARDS=y
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+# CONFIG_CRYPTO_SEQIV is not set
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_HW is not set
--
1.5.3
--
yamahata
^ permalink raw reply related [flat|nested] 45+ messages in thread
* Re: [PATCH 20/28] ia64/xen: domU xen machine vector without dma api.
[not found] ` <20080221091904.811793000@ls.local.valinux.co.jp>
@ 2008-02-21 23:08 ` Jeremy Fitzhardinge
0 siblings, 0 replies; 45+ messages in thread
From: Jeremy Fitzhardinge @ 2008-02-21 23:08 UTC (permalink / raw)
To: yamahata; +Cc: virtualization, linux-ia64, kvm-ia64-devel, xen-ia64-devel
yamahata@valinux.co.jp wrote:
> diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
> index 78f28d8..9c17a46 100644
> --- a/arch/ia64/kernel/acpi.c
> +++ b/arch/ia64/kernel/acpi.c
> @@ -118,6 +118,10 @@ acpi_get_sysname(void)
> return "hpzx1";
> } else if (!strcmp(hdr->oem_id, "SGI")) {
> return "sn2";
> +#ifdef CONFIG_XEN
> + } else if (is_running_on_xen() && !strcmp(hdr->oem_id, "XEN")) {
> + return "xen";
> +#endif
> }
Is the #ifdef necessary? Couldn't you make is_running_on_xen() just
evaluate to 0 in the non-Xen case?
J
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 24/28] ia64/xen: time paravirtualization
@ 2008-02-21 23:11 ` Jeremy Fitzhardinge
2008-02-22 3:57 ` Isaku Yamahata
` (2 more replies)
0 siblings, 3 replies; 45+ messages in thread
From: Jeremy Fitzhardinge @ 2008-02-21 23:11 UTC (permalink / raw)
To: linux-ia64
yamahata@valinux.co.jp wrote:
> diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
> index 17fda52..1bb0362 100644
> --- a/arch/ia64/kernel/time.c
> +++ b/arch/ia64/kernel/time.c
> @@ -29,6 +29,14 @@
> #include <asm/sections.h>
> #include <asm/system.h>
>
> +#include <asm/xen/hypervisor.h>
> +#ifdef CONFIG_XEN
> +#include <linux/kernel_stat.h>
> +#include <linux/posix-timers.h>
> +#include <xen/interface/vcpu.h>
> +#include <asm/percpu.h>
> +#endif
> +
ia64 doesn't use clocksources yet? Couldn't you share a lot of this
with the 32-bit Xen time code (esp stolen time accounting)?
J
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 24/28] ia64/xen: time paravirtualization
[not found] ` <20080221091906.007909000@ls.local.valinux.co.jp>
2008-02-21 23:11 ` [PATCH 24/28] ia64/xen: time paravirtualization Jeremy Fitzhardinge
@ 2008-02-21 23:11 ` Jeremy Fitzhardinge
1 sibling, 0 replies; 45+ messages in thread
From: Jeremy Fitzhardinge @ 2008-02-21 23:11 UTC (permalink / raw)
To: yamahata; +Cc: virtualization, linux-ia64, kvm-ia64-devel, xen-ia64-devel
yamahata@valinux.co.jp wrote:
> diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
> index 17fda52..1bb0362 100644
> --- a/arch/ia64/kernel/time.c
> +++ b/arch/ia64/kernel/time.c
> @@ -29,6 +29,14 @@
> #include <asm/sections.h>
> #include <asm/system.h>
>
> +#include <asm/xen/hypervisor.h>
> +#ifdef CONFIG_XEN
> +#include <linux/kernel_stat.h>
> +#include <linux/posix-timers.h>
> +#include <xen/interface/vcpu.h>
> +#include <asm/percpu.h>
> +#endif
> +
ia64 doesn't use clocksources yet? Couldn't you share a lot of this
with the 32-bit Xen time code (esp stolen time accounting)?
J
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 19/28] ia64/xen: xen domU irq chip introducing some helper functions, xen_send_ipi.
[not found] ` <20080221091904.517166000@ls.local.valinux.co.jp>
@ 2008-02-21 23:22 ` Jeremy Fitzhardinge
0 siblings, 0 replies; 45+ messages in thread
From: Jeremy Fitzhardinge @ 2008-02-21 23:22 UTC (permalink / raw)
To: yamahata; +Cc: virtualization, linux-ia64, kvm-ia64-devel, xen-ia64-devel
yamahata@valinux.co.jp wrote:
> diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
> index 0b52f19..b5dcb49 100644
> --- a/arch/ia64/kernel/irq_ia64.c
> +++ b/arch/ia64/kernel/irq_ia64.c
> @@ -30,6 +30,9 @@
> #include <linux/threads.h>
> #include <linux/bitops.h>
> #include <linux/irq.h>
> +#ifdef CONFIG_XEN
> +#include <linux/cpu.h>
> +#endif
>
> #include <asm/delay.h>
> #include <asm/intrinsics.h>
> @@ -204,6 +207,13 @@ assign_irq_vector (int irq)
>
> vector = -ENOSPC;
>
> +#ifdef CONFIG_XEN
> + if (is_running_on_xen()) {
> + extern int xen_assign_irq_vector(int);
> + return xen_assign_irq_vector(irq);
> + }
> +#endif
>
No extern prototypes in .c files; definitely not nested in block scope
(here and elsewhere in the series).
> +static char timer_name[NR_CPUS][15];
> +static char ipi_name[NR_CPUS][15];
> +static char resched_name[NR_CPUS][15];
> +static char cmc_name[NR_CPUS][15];
> +static char cmcp_name[NR_CPUS][15];
> +static char cpep_name[NR_CPUS][15];
Why not use percpu?
> +/* FIXME: There's no obvious point to check whether slab is ready. So
> + * a hack is used here by utilizing a late time hook.
> + */
Could you hook onto paravirt_post_allocator_init()?
J
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 21/28] ia64/xen: define xen related address conversion helper functions for domU
[not found] ` <20080221091905.122606000@ls.local.valinux.co.jp>
@ 2008-02-21 23:45 ` Jeremy Fitzhardinge
0 siblings, 0 replies; 45+ messages in thread
From: Jeremy Fitzhardinge @ 2008-02-21 23:45 UTC (permalink / raw)
To: yamahata; +Cc: virtualization, linux-ia64, kvm-ia64-devel, xen-ia64-devel
yamahata@valinux.co.jp wrote:
> diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
> index 4999a6c..effd2af 100644
> --- a/include/asm-ia64/page.h
> +++ b/include/asm-ia64/page.h
> @@ -227,4 +227,15 @@ get_order (unsigned long size)
> (((current->personality & READ_IMPLIES_EXEC) != 0) \
> ? VM_EXEC : 0))
>
> +#ifndef __ASSEMBLY__
> +
> +#include <linux/kernel.h>
>
Why? asm-ia64/xen/page.h already includes this.
> +
> +#ifdef CONFIG_XEN
> +
> +#include <asm/xen/page.h>
>
This shouldn't be necessary; anyone wanting Xen-specific definitions
should explicitly include <xen/page.h>.
> +
> +#endif /* CONFIG_XEN */
> +#endif /* __ASSEMBLY__ */
> +
> #endif /* _ASM_IA64_PAGE_H */
> diff --git a/include/asm-ia64/xen/page.h b/include/asm-ia64/xen/page.h
> new file mode 100644
> index 0000000..9ab8148
> --- /dev/null
> +++ b/include/asm-ia64/xen/page.h
> @@ -0,0 +1,19 @@
> +#ifndef _ASM_IA64_MADDR_H
> +#define _ASM_IA64_MADDR_H
> +
> +#include <linux/kernel.h>
> +#include <asm/xen/hypervisor.h>
> +#include <asm/xen/hypercall.h>
> +#include <xen/features.h>
> +#include <xen/interface/xen.h>
> +
> +#define mfn_to_pfn(mfn) (mfn)
> +#define pfn_to_mfn(pfn) (pfn)
> +
> +#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT))
> +#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT)
> +#define virt_to_machine(virt) __pa(virt) /* for tpmfront.c */
> +
> +#define set_phys_to_machine(pfn, mfn) do { } while (0)
>
Probably worth turning these into inlines so that they get properly
typechecked. Especially things like set_phys_to_machine(), which
doesn't use its arguments.
J
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary
@ 2008-02-21 23:47 ` Jeremy Fitzhardinge
2008-02-22 3:54 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU Isaku Yamahata
` (2 more replies)
0 siblings, 3 replies; 45+ messages in thread
From: Jeremy Fitzhardinge @ 2008-02-21 23:47 UTC (permalink / raw)
To: linux-ia64
yamahata@valinux.co.jp wrote:
> +static inline unsigned long
> +HYPERVISOR_machtophys(unsigned long mfn)
> +{
> + unsigned long ret = mfn;
> + if (is_running_on_xen())
>
Do you often call hypercalls when not booting under Xen? It seems to me
this check should have already been done at a higher layer, and it
needn't be repeated here.
> + ret = __HYPERVISOR_machtophys(mfn);
> + return ret;
> +}
J
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU.
[not found] ` <20080221091902.716789000@ls.local.valinux.co.jp>
@ 2008-02-21 23:47 ` Jeremy Fitzhardinge
2008-02-21 23:47 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary Jeremy Fitzhardinge
1 sibling, 0 replies; 45+ messages in thread
From: Jeremy Fitzhardinge @ 2008-02-21 23:47 UTC (permalink / raw)
To: yamahata; +Cc: virtualization, linux-ia64, kvm-ia64-devel, xen-ia64-devel
yamahata@valinux.co.jp wrote:
> +static inline unsigned long
> +HYPERVISOR_machtophys(unsigned long mfn)
> +{
> + unsigned long ret = mfn;
> + if (is_running_on_xen())
>
Do you often call hypercalls when not booting under Xen? It seems to me
this check should have already been done at a higher layer, and it
needn't be repeated here.
> + ret = __HYPERVISOR_machtophys(mfn);
> + return ret;
> +}
J
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU.
2008-02-21 23:47 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary Jeremy Fitzhardinge
2008-02-22 3:54 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU Isaku Yamahata
@ 2008-02-22 3:54 ` Isaku Yamahata
2008-02-25 18:36 ` [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall " Dong, Eddie
2008-02-25 18:36 ` Dong, Eddie
2008-02-22 5:10 ` [PATCH 13/28] ia64/xen: introduce xen hypercall " Isaku Yamahata
2 siblings, 2 replies; 45+ messages in thread
From: Isaku Yamahata @ 2008-02-22 3:54 UTC (permalink / raw)
To: linux-ia64
On Thu, Feb 21, 2008 at 03:47:10PM -0800, Jeremy Fitzhardinge wrote:
> yamahata@valinux.co.jp wrote:
> >+static inline unsigned long
> >+HYPERVISOR_machtophys(unsigned long mfn)
> >+{
> >+ unsigned long ret = mfn;
> >+ if (is_running_on_xen())
> >
>
> Do you often call hypercalls when not booting under Xen? It seems to me
> this check should have already been done at a higher layer, and it
> needn't be repeated here.
IA64 pv_ops frame work doesn't exist yet so that xen code does
in order to boot on both native and xen for now.
I expect those check will be eliminated during developing ia64 pv_ops.
--
yamahata
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU.
2008-02-21 23:47 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary Jeremy Fitzhardinge
@ 2008-02-22 3:54 ` Isaku Yamahata
2008-02-22 3:54 ` Isaku Yamahata
2008-02-22 5:10 ` [PATCH 13/28] ia64/xen: introduce xen hypercall " Isaku Yamahata
2 siblings, 0 replies; 45+ messages in thread
From: Isaku Yamahata @ 2008-02-22 3:54 UTC (permalink / raw)
To: Jeremy Fitzhardinge
Cc: virtualization, linux-ia64, kvm-ia64-devel, xen-ia64-devel
On Thu, Feb 21, 2008 at 03:47:10PM -0800, Jeremy Fitzhardinge wrote:
> yamahata@valinux.co.jp wrote:
> >+static inline unsigned long
> >+HYPERVISOR_machtophys(unsigned long mfn)
> >+{
> >+ unsigned long ret = mfn;
> >+ if (is_running_on_xen())
> >
>
> Do you often call hypercalls when not booting under Xen? It seems to me
> this check should have already been done at a higher layer, and it
> needn't be repeated here.
IA64 pv_ops frame work doesn't exist yet so that xen code does
in order to boot on both native and xen for now.
I expect those check will be eliminated during developing ia64 pv_ops.
--
yamahata
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 24/28] ia64/xen: time paravirtualization
2008-02-21 23:11 ` [PATCH 24/28] ia64/xen: time paravirtualization Jeremy Fitzhardinge
@ 2008-02-22 3:57 ` Isaku Yamahata
2008-02-22 3:57 ` Isaku Yamahata
2008-02-22 5:10 ` Isaku Yamahata
2 siblings, 0 replies; 45+ messages in thread
From: Isaku Yamahata @ 2008-02-22 3:57 UTC (permalink / raw)
To: linux-ia64
On Thu, Feb 21, 2008 at 03:11:04PM -0800, Jeremy Fitzhardinge wrote:
> yamahata@valinux.co.jp wrote:
> >diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
> >index 17fda52..1bb0362 100644
> >--- a/arch/ia64/kernel/time.c
> >+++ b/arch/ia64/kernel/time.c
> >@@ -29,6 +29,14 @@
> > #include <asm/sections.h>
> > #include <asm/system.h>
> >
> >+#include <asm/xen/hypervisor.h>
> >+#ifdef CONFIG_XEN
> >+#include <linux/kernel_stat.h>
> >+#include <linux/posix-timers.h>
> >+#include <xen/interface/vcpu.h>
> >+#include <asm/percpu.h>
> >+#endif
> >+
>
> ia64 doesn't use clocksources yet? Couldn't you share a lot of this
> with the 32-bit Xen time code (esp stolen time accounting)?
It does. I'll look into sharing code.
(Probably after cpu paravirtualization)
--
yamahata
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 24/28] ia64/xen: time paravirtualization
2008-02-21 23:11 ` [PATCH 24/28] ia64/xen: time paravirtualization Jeremy Fitzhardinge
2008-02-22 3:57 ` Isaku Yamahata
@ 2008-02-22 3:57 ` Isaku Yamahata
2008-02-22 5:10 ` Isaku Yamahata
2 siblings, 0 replies; 45+ messages in thread
From: Isaku Yamahata @ 2008-02-22 3:57 UTC (permalink / raw)
To: Jeremy Fitzhardinge
Cc: virtualization, linux-ia64, kvm-ia64-devel, xen-ia64-devel
On Thu, Feb 21, 2008 at 03:11:04PM -0800, Jeremy Fitzhardinge wrote:
> yamahata@valinux.co.jp wrote:
> >diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
> >index 17fda52..1bb0362 100644
> >--- a/arch/ia64/kernel/time.c
> >+++ b/arch/ia64/kernel/time.c
> >@@ -29,6 +29,14 @@
> > #include <asm/sections.h>
> > #include <asm/system.h>
> >
> >+#include <asm/xen/hypervisor.h>
> >+#ifdef CONFIG_XEN
> >+#include <linux/kernel_stat.h>
> >+#include <linux/posix-timers.h>
> >+#include <xen/interface/vcpu.h>
> >+#include <asm/percpu.h>
> >+#endif
> >+
>
> ia64 doesn't use clocksources yet? Couldn't you share a lot of this
> with the 32-bit Xen time code (esp stolen time accounting)?
It does. I'll look into sharing code.
(Probably after cpu paravirtualization)
--
yamahata
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU.
2008-02-21 23:47 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary Jeremy Fitzhardinge
2008-02-22 3:54 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU Isaku Yamahata
2008-02-22 3:54 ` Isaku Yamahata
@ 2008-02-22 5:10 ` Isaku Yamahata
2 siblings, 0 replies; 45+ messages in thread
From: Isaku Yamahata @ 2008-02-22 5:10 UTC (permalink / raw)
To: linux-ia64
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/xen/hypercall.S | 7 +
include/asm-ia64/xen/hypercall.h | 426 ++++++++++++++++++++++++++++++++++++++
2 files changed, 433 insertions(+), 0 deletions(-)
create mode 100644 include/asm-ia64/xen/hypercall.h
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
index a96f278..7c5242b 100644
--- a/arch/ia64/xen/hypercall.S
+++ b/arch/ia64/xen/hypercall.S
@@ -122,3 +122,10 @@ GLOBAL_ENTRY(xen_set_eflag)
END(xen_set_eflag)
#endif /* CONFIG_IA32_SUPPORT */
#endif /* ASM_SUPPORTED */
+
+GLOBAL_ENTRY(__hypercall)
+ mov r2=r37
+ break 0x1000
+ br.ret.sptk.many b0
+ ;;
+END(__hypercall)
diff --git a/include/asm-ia64/xen/hypercall.h b/include/asm-ia64/xen/hypercall.h
new file mode 100644
index 0000000..8ea2060
--- /dev/null
+++ b/include/asm-ia64/xen/hypercall.h
@@ -0,0 +1,426 @@
+/******************************************************************************
+ * hypercall.h
+ *
+ * Linux-specific hypervisor handling.
+ *
+ * Copyright (c) 2002-2004, K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERCALL_H__
+#define __HYPERCALL_H__
+
+#ifndef __HYPERVISOR_H__
+# error "please don't include this file directly"
+#endif
+
+#include <asm/xen/xcom_hcall.h>
+struct xencomm_handle;
+extern unsigned long __hypercall(unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4,
+ unsigned long a5, unsigned long cmd);
+
+/*
+ * Assembler stubs for hyper-calls.
+ */
+
+#define _hypercall0(type, name) \
+({ \
+ long __res; \
+ __res = __hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name);\
+ (type)__res; \
+})
+
+#define _hypercall1(type, name, a1) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ 0, 0, 0, 0, __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+#define _hypercall2(type, name, a1, a2) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ (unsigned long)a2, \
+ 0, 0, 0, __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+#define _hypercall3(type, name, a1, a2, a3) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ (unsigned long)a2, \
+ (unsigned long)a3, \
+ 0, 0, __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+#define _hypercall4(type, name, a1, a2, a3, a4) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ (unsigned long)a2, \
+ (unsigned long)a3, \
+ (unsigned long)a4, \
+ 0, __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
+({ \
+ long __res; \
+ __res = __hypercall((unsigned long)a1, \
+ (unsigned long)a2, \
+ (unsigned long)a3, \
+ (unsigned long)a4, \
+ (unsigned long)a5, \
+ __HYPERVISOR_##name); \
+ (type)__res; \
+})
+
+
+static inline int
+xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, sched_op, cmd, arg);
+}
+
+static inline long
+HYPERVISOR_set_timer_op(u64 timeout)
+{
+ unsigned long timeout_hi = (unsigned long)(timeout >> 32);
+ unsigned long timeout_lo = (unsigned long)timeout;
+ return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
+}
+
+static inline int
+xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list,
+ int nr_calls)
+{
+ return _hypercall2(int, multicall, call_list, nr_calls);
+}
+
+static inline int
+xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, memory_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, event_channel_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, xen_version, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_console_io(int cmd, int count,
+ struct xencomm_handle *str)
+{
+ return _hypercall3(int, console_io, cmd, count, str);
+}
+
+static inline int
+xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, physdev_op, cmd, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_grant_table_op(unsigned int cmd,
+ struct xencomm_handle *uop,
+ unsigned int count)
+{
+ return _hypercall3(int, grant_table_op, cmd, uop, count);
+}
+
+int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
+
+extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg);
+
+static inline int
+xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, callback_op, cmd, arg);
+}
+
+static inline unsigned long
+xencomm_arch_hypercall_hvm_op(int cmd, void *arg)
+{
+ return _hypercall2(unsigned long, hvm_op, cmd, arg);
+}
+
+static inline long
+xencomm_arch_hypercall_vcpu_op(int cmd, int cpu, void *arg)
+{
+ return _hypercall3(long, vcpu_op, cmd, cpu, arg);
+}
+
+static inline int
+HYPERVISOR_physdev_op(int cmd, void *arg)
+{
+ switch (cmd) {
+ case PHYSDEVOP_eoi:
+ return _hypercall1(int, ia64_fast_eoi,
+ ((struct physdev_eoi *)arg)->irq);
+ default:
+ return xencomm_hypercall_physdev_op(cmd, arg);
+ }
+}
+
+static inline int
+xencomm_arch_hypercall_xenoprof_op(int op, struct xencomm_handle *arg)
+{
+ return _hypercall2(int, xenoprof_op, op, arg);
+}
+
+static inline long
+xencomm_arch_hypercall_opt_feature(struct xencomm_handle *arg)
+{
+ return _hypercall1(long, opt_feature, arg);
+}
+
+#define xen_do_IRQ(irq, regs) \
+do { \
+ struct pt_regs *old_regs; \
+ old_regs = set_irq_regs(regs); \
+ irq_enter(); \
+ __do_IRQ(irq); \
+ irq_exit(); \
+ set_irq_regs(old_regs); \
+} while (0)
+#define irq_ctx_init(cpu) do { } while (0)
+
+#include <linux/err.h>
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
+
+static inline unsigned long
+__HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
+{
+ return _hypercall3(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_ioremap, ioaddr, size);
+}
+
+static inline unsigned long
+HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size)
+{
+ unsigned long ret = ioaddr;
+ if (is_running_on_xen()) {
+ ret = __HYPERVISOR_ioremap(ioaddr, size);
+ if (unlikely(ret = -ENOSYS))
+ panic("hypercall %s failed with %ld. "
+ "Please check Xen and Linux config mismatch\n",
+ __func__, -ret);
+ else if (unlikely(IS_ERR_VALUE(ret)))
+ ret = ioaddr;
+ }
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_phystomach(unsigned long gpfn)
+{
+ return _hypercall2(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_phystomach, gpfn);
+}
+
+static inline unsigned long
+HYPERVISOR_phystomach(unsigned long gpfn)
+{
+ unsigned long ret = gpfn;
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_phystomach(gpfn);
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_machtophys(unsigned long mfn)
+{
+ return _hypercall2(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_machtophys, mfn);
+}
+
+static inline unsigned long
+HYPERVISOR_machtophys(unsigned long mfn)
+{
+ unsigned long ret = mfn;
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_machtophys(mfn);
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
+{
+ return _hypercall3(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_zap_physmap, gpfn, extent_order);
+}
+
+static inline unsigned long
+HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order)
+{
+ unsigned long ret = 0;
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_zap_physmap(gpfn, extent_order);
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
+ unsigned long flags, domid_t domid)
+{
+ return _hypercall5(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_add_physmap, gpfn, mfn, flags, domid);
+}
+
+static inline unsigned long
+HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
+ unsigned long flags, domid_t domid)
+{
+ unsigned long ret = 0;
+ BUG_ON(!is_running_on_xen());
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_add_physmap(gpfn, mfn, flags, domid);
+ return ret;
+}
+
+static inline unsigned long
+__HYPERVISOR_add_physmap_with_gmfn(unsigned long gpfn, unsigned long gmfn,
+ unsigned long flags, domid_t domid)
+{
+ return _hypercall5(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_add_physmap_with_gmfn,
+ gpfn, gmfn, flags, domid);
+}
+
+static inline unsigned long
+HYPERVISOR_add_physmap_with_gmfn(unsigned long gpfn, unsigned long gmfn,
+ unsigned long flags, domid_t domid)
+{
+ unsigned long ret = 0;
+ BUG_ON(!is_running_on_xen());
+ if (is_running_on_xen())
+ ret = __HYPERVISOR_add_physmap_with_gmfn(gpfn, gmfn,
+ flags, domid);
+ return ret;
+}
+
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
+static inline unsigned long
+HYPERVISOR_expose_p2m(unsigned long conv_start_gpfn,
+ unsigned long assign_start_gpfn,
+ unsigned long expose_size, unsigned long granule_pfn)
+{
+ return _hypercall5(unsigned long, ia64_dom0vp_op,
+ IA64_DOM0VP_expose_p2m, conv_start_gpfn,
+ assign_start_gpfn, expose_size, granule_pfn);
+}
+
+static inline int
+xencomm_arch_expose_foreign_p2m(unsigned long gpfn,
+ domid_t domid, struct xencomm_handle *arg,
+ unsigned long flags)
+{
+ return _hypercall5(int, ia64_dom0vp_op,
+ IA64_DOM0VP_expose_foreign_p2m,
+ gpfn, domid, arg, flags);
+}
+
+static inline int
+HYPERVISOR_unexpose_foreign_p2m(unsigned long gpfn, domid_t domid)
+{
+ return _hypercall3(int, ia64_dom0vp_op,
+ IA64_DOM0VP_unexpose_foreign_p2m, gpfn, domid);
+}
+#endif
+
+static inline int
+xencomm_arch_hypercall_perfmon_op(unsigned long cmd,
+ struct xencomm_handle *arg,
+ unsigned long count)
+{
+ return _hypercall4(int, ia64_dom0vp_op,
+ IA64_DOM0VP_perfmon, cmd, arg, count);
+}
+
+static inline int
+xencomm_arch_hypercall_fpswa_revision(struct xencomm_handle *arg)
+{
+ return _hypercall2(int, ia64_dom0vp_op,
+ IA64_DOM0VP_fpswa_revision, arg);
+}
+
+static inline int
+xencomm_arch_hypercall_ia64_debug_op(unsigned long cmd,
+ unsigned long domain,
+ struct xencomm_handle *arg)
+{
+ return _hypercall3(int, ia64_debug_op, cmd, domain, arg);
+}
+
+static inline int
+HYPERVISOR_add_io_space(unsigned long phys_base,
+ unsigned long sparse,
+ unsigned long space_number)
+{
+ return _hypercall4(int, ia64_dom0vp_op, IA64_DOM0VP_add_io_space,
+ phys_base, sparse, space_number);
+}
+
+/* for balloon driver */
+#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
+
+/* Use xencomm to do hypercalls. */
+#define HYPERVISOR_sched_op xencomm_hypercall_sched_op
+#define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op
+#define HYPERVISOR_callback_op xencomm_hypercall_callback_op
+#define HYPERVISOR_multicall xencomm_hypercall_multicall
+#define HYPERVISOR_xen_version xencomm_hypercall_xen_version
+#define HYPERVISOR_console_io xencomm_hypercall_console_io
+#define HYPERVISOR_hvm_op xencomm_hypercall_hvm_op
+#define HYPERVISOR_memory_op xencomm_hypercall_memory_op
+#define HYPERVISOR_xenoprof_op xencomm_hypercall_xenoprof_op
+#define HYPERVISOR_perfmon_op xencomm_hypercall_perfmon_op
+#define HYPERVISOR_fpswa_revision xencomm_hypercall_fpswa_revision
+#define HYPERVISOR_suspend xencomm_hypercall_suspend
+#define HYPERVISOR_vcpu_op xencomm_hypercall_vcpu_op
+#define HYPERVISOR_opt_feature xencomm_hypercall_opt_feature
+#define HYPERVISOR_kexec_op xencomm_hypercall_kexec_op
+
+/* to compile gnttab_copy_grant_page() in drivers/xen/core/gnttab.c */
+#define HYPERVISOR_mmu_update(req, count, success_count, domid) ({ BUG(); 0; })
+
+#endif /* __HYPERCALL_H__ */
--
1.5.3
^ permalink raw reply related [flat|nested] 45+ messages in thread
* [PATCH 24/28] ia64/xen: time paravirtualization
2008-02-21 23:11 ` [PATCH 24/28] ia64/xen: time paravirtualization Jeremy Fitzhardinge
2008-02-22 3:57 ` Isaku Yamahata
2008-02-22 3:57 ` Isaku Yamahata
@ 2008-02-22 5:10 ` Isaku Yamahata
2 siblings, 0 replies; 45+ messages in thread
From: Isaku Yamahata @ 2008-02-22 5:10 UTC (permalink / raw)
To: linux-ia64
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
---
arch/ia64/kernel/time.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 204 insertions(+), 0 deletions(-)
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 17fda52..1bb0362 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -29,6 +29,14 @@
#include <asm/sections.h>
#include <asm/system.h>
+#include <asm/xen/hypervisor.h>
+#ifdef CONFIG_XEN
+#include <linux/kernel_stat.h>
+#include <linux/posix-timers.h>
+#include <xen/interface/vcpu.h>
+#include <asm/percpu.h>
+#endif
+
#include "fsyscall_gtod_data.h"
static cycle_t itc_get_cycles(void);
@@ -38,6 +46,17 @@ struct fsyscall_gtod_data_t fsyscall_gtod_data = {
};
struct itc_jitter_data_t itc_jitter_data;
+#ifdef CONFIG_XEN
+static void itc_jitter_data_reset(void)
+{
+ u64 lcycle, ret;
+
+ do {
+ lcycle = itc_jitter_data.itc_lastcycle;
+ ret = cmpxchg(&itc_jitter_data.itc_lastcycle, lcycle, 0);
+ } while (unlikely(ret != lcycle));
+}
+#endif
volatile int time_keeper_id = 0; /* smp_processor_id() of time-keeper */
@@ -56,13 +75,105 @@ static struct clocksource clocksource_itc = {
.mult = 0, /*to be calculated*/
.shift = 16,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+#ifdef CONFIG_XEN
+ .resume = itc_jitter_data_reset,
+#endif
};
static struct clocksource *itc_clocksource;
+#ifdef CONFIG_XEN
+DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
+DEFINE_PER_CPU(unsigned long, processed_stolen_time);
+DEFINE_PER_CPU(unsigned long, processed_blocked_time);
+#define NS_PER_TICK (1000000000LL/HZ)
+static unsigned long
+consider_steal_time(unsigned long new_itm)
+{
+ unsigned long stolen, blocked, sched_time;
+ unsigned long delta_itm = 0, stolentick = 0;
+ int cpu = smp_processor_id();
+ struct vcpu_runstate_info *runstate;
+ struct task_struct *p = current;
+
+ runstate = &per_cpu(runstate, smp_processor_id());
+
+ do {
+ sched_time = runstate->state_entry_time;
+ mb();
+ stolen = runstate->time[RUNSTATE_runnable] +
+ runstate->time[RUNSTATE_offline] -
+ per_cpu(processed_stolen_time, cpu);
+ blocked = runstate->time[RUNSTATE_blocked] -
+ per_cpu(processed_blocked_time, cpu);
+ mb();
+ } while (sched_time != runstate->state_entry_time);
+
+ /*
+ * Check for vcpu migration effect
+ * In this case, itc value is reversed.
+ * This causes huge stolen value.
+ * This function just checks and reject this effect.
+ */
+ if (!time_after_eq(runstate->time[RUNSTATE_blocked],
+ per_cpu(processed_blocked_time, cpu)))
+ blocked = 0;
+
+ if (!time_after_eq(runstate->time[RUNSTATE_runnable] +
+ runstate->time[RUNSTATE_offline],
+ per_cpu(processed_stolen_time, cpu)))
+ stolen = 0;
+
+ if (!time_after(delta_itm + new_itm, ia64_get_itc()))
+ stolentick = ia64_get_itc() - delta_itm - new_itm;
+
+ do_div(stolentick, NS_PER_TICK);
+ stolentick++;
+
+ do_div(stolen, NS_PER_TICK);
+
+ if (stolen > stolentick)
+ stolen = stolentick;
+
+ stolentick -= stolen;
+ do_div(blocked, NS_PER_TICK);
+
+ if (blocked > stolentick)
+ blocked = stolentick;
+
+ if (stolen > 0 || blocked > 0) {
+ account_steal_time(NULL, jiffies_to_cputime(stolen));
+ account_steal_time(idle_task(cpu), jiffies_to_cputime(blocked));
+ run_local_timers();
+
+ if (rcu_pending(cpu))
+ rcu_check_callbacks(cpu, user_mode(get_irq_regs()));
+
+ scheduler_tick();
+ run_posix_cpu_timers(p);
+ delta_itm += local_cpu_data->itm_delta * (stolen + blocked);
+
+ if (cpu = time_keeper_id) {
+ write_seqlock(&xtime_lock);
+ do_timer(stolen + blocked);
+ local_cpu_data->itm_next = delta_itm + new_itm;
+ write_sequnlock(&xtime_lock);
+ } else {
+ local_cpu_data->itm_next = delta_itm + new_itm;
+ }
+ per_cpu(processed_stolen_time, cpu) += NS_PER_TICK * stolen;
+ per_cpu(processed_blocked_time, cpu) += NS_PER_TICK * blocked;
+ }
+ return delta_itm;
+}
+#else
+#define consider_steal_time(new_itm) (0)
+#endif
+
static irqreturn_t
timer_interrupt (int irq, void *dev_id)
{
unsigned long new_itm;
+ unsigned long delta_itm; /* XEN */
if (unlikely(cpu_is_offline(smp_processor_id()))) {
return IRQ_HANDLED;
@@ -78,6 +189,13 @@ timer_interrupt (int irq, void *dev_id)
profile_tick(CPU_PROFILING);
+ if (is_running_on_xen()) {
+ delta_itm = consider_steal_time(new_itm);
+ new_itm += delta_itm;
+ if (time_after(new_itm, ia64_get_itc()) && delta_itm)
+ goto skip_process_time_accounting;
+ }
+
while (1) {
update_process_times(user_mode(get_irq_regs()));
@@ -107,6 +225,8 @@ timer_interrupt (int irq, void *dev_id)
local_irq_disable();
}
+skip_process_time_accounting: /* XEN */
+
do {
/*
* If we're too close to the next clock tick for
@@ -161,6 +281,84 @@ static int __init nojitter_setup(char *str)
__setup("nojitter", nojitter_setup);
+#ifdef CONFIG_XEN
+/* taken from i386/kernel/time-xen.c */
+static void init_missing_ticks_accounting(int cpu)
+{
+ struct vcpu_register_runstate_memory_area area;
+ struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu);
+ int rc;
+
+ memset(runstate, 0, sizeof(*runstate));
+
+ area.addr.v = runstate;
+ rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu,
+ &area);
+ WARN_ON(rc && rc != -ENOSYS);
+
+ per_cpu(processed_blocked_time, cpu) = runstate->time[RUNSTATE_blocked];
+ per_cpu(processed_stolen_time, cpu) = runstate->time[RUNSTATE_runnable]
+ + runstate->time[RUNSTATE_offline];
+}
+
+static int xen_ia64_settimefoday_after_resume;
+
+static int __init __xen_ia64_settimeofday_after_resume(char *str)
+{
+ xen_ia64_settimefoday_after_resume = 1;
+ return 1;
+}
+
+__setup("xen_ia64_settimefoday_after_resume",
+ __xen_ia64_settimeofday_after_resume);
+
+/* Called after suspend, to resume time. */
+void
+time_resume(void)
+{
+ unsigned int cpu;
+
+ /* Just trigger a tick. */
+ ia64_cpu_local_tick();
+
+ if (xen_ia64_settimefoday_after_resume) {
+ /* do_settimeofday() resets timer interplator */
+ struct timespec xen_time;
+ int ret;
+ efi_gettimeofday(&xen_time);
+
+ ret = do_settimeofday(&xen_time);
+ WARN_ON(ret);
+ } else {
+#if 0
+ /* adjust EFI time */
+ struct timespec my_time = CURRENT_TIME;
+ struct timespec xen_time;
+ static timespec diff;
+ struct xen_domctl domctl;
+ int ret;
+
+ efi_gettimeofday(&xen_time);
+ diff = timespec_sub(&xen_time, &my_time);
+ domctl.cmd = XEN_DOMCTL_settimeoffset;
+ domctl.domain = DOMID_SELF;
+ domctl.u.settimeoffset.timeoffset_seconds = diff.tv_sec;
+ ret = HYPERVISOR_domctl_op(&domctl);
+ WARN_ON(ret);
+#endif
+ /* itc_clocksource remembers the last timer status in
+ * itc_jitter_data. Forget it */
+ clocksource_resume();
+ }
+
+ for_each_online_cpu(cpu)
+ init_missing_ticks_accounting(cpu);
+
+ touch_softlockup_watchdog();
+}
+#else
+#define init_missing_ticks_accounting(cpu) do {} while (0)
+#endif
void __devinit
ia64_init_itm (void)
@@ -256,6 +454,12 @@ ia64_init_itm (void)
*/
clocksource_itc.rating = 50;
+ if (is_running_on_xen())
+ init_missing_ticks_accounting(smp_processor_id());
+
+ /* avoid softlock up message when cpu is unplug and plugged again. */
+ touch_softlockup_watchdog();
+
/* Setup the CPU local timer tick */
ia64_cpu_local_tick();
--
1.5.3
^ permalink raw reply related [flat|nested] 45+ messages in thread
* RE: [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall routines necessary for domU.
@ 2008-02-25 18:36 ` Dong, Eddie
2008-02-26 1:44 ` Isaku Yamahata
2008-02-26 1:44 ` Isaku Yamahata
0 siblings, 2 replies; 45+ messages in thread
From: Dong, Eddie @ 2008-02-25 18:36 UTC (permalink / raw)
To: linux-ia64
> IA64 pv_ops frame work doesn't exist yet so that xen code does
> in order to boot on both native and xen for now.
> I expect those check will be eliminated during developing ia64 pv_ops.
Qing He & I am working on the pv_ops framework, hopefully we can get
a draft soon :)
Eddie
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall routines necessary for domU.
2008-02-22 3:54 ` Isaku Yamahata
2008-02-25 18:36 ` [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall " Dong, Eddie
@ 2008-02-25 18:36 ` Dong, Eddie
1 sibling, 0 replies; 45+ messages in thread
From: Dong, Eddie @ 2008-02-25 18:36 UTC (permalink / raw)
To: Isaku Yamahata, Jeremy Fitzhardinge
Cc: xen-ia64-devel, linux-ia64, kvm-ia64-devel, virtualization
> IA64 pv_ops frame work doesn't exist yet so that xen code does
> in order to boot on both native and xen for now.
> I expect those check will be eliminated during developing ia64 pv_ops.
Qing He & I am working on the pv_ops framework, hopefully we can get
a draft soon :)
Eddie
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall routines necessary for domU.
2008-02-25 18:36 ` [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall " Dong, Eddie
@ 2008-02-26 1:44 ` Isaku Yamahata
2008-02-26 1:44 ` Isaku Yamahata
1 sibling, 0 replies; 45+ messages in thread
From: Isaku Yamahata @ 2008-02-26 1:44 UTC (permalink / raw)
To: linux-ia64
On Tue, Feb 26, 2008 at 02:36:51AM +0800, Dong, Eddie wrote:
>
> > IA64 pv_ops frame work doesn't exist yet so that xen code does
> > in order to boot on both native and xen for now.
> > I expect those check will be eliminated during developing ia64 pv_ops.
>
> Qing He & I am working on the pv_ops framework, hopefully we can get
> a draft soon :)
Great!
What I am aware of at this moment is,
(some of the following can be covered by machine vector, though.)
- early setup before start_kernel()
Currently early_xen_setup() is directly called.
Eventually extending ia64 boot protocol would be necessary, though.
- Initialization hooks
struct pv_init_ops?
void (*arch_setup_early)(void)
void (*banner);
void (*pre_pasing_init)(void);
void (*post_pasing_init)(void);
void (*post_allocator_init)(void);
- irq hooks
struct pv_irq_ops
- init_IRQ(), irq_init()
- registering chip type
register_intr()
- assign_irq_vector()
- free_irq_vector()
- register_percpu_irq()
- send_ipi()
- resend_irq()
- IOSAPIC hooks
struct pv_iosapic_ops
- iosapic_init()
- iosapic_read()
- iosapic_write()
--
yamahata
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall routines necessary for domU.
2008-02-25 18:36 ` [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall " Dong, Eddie
2008-02-26 1:44 ` Isaku Yamahata
@ 2008-02-26 1:44 ` Isaku Yamahata
1 sibling, 0 replies; 45+ messages in thread
From: Isaku Yamahata @ 2008-02-26 1:44 UTC (permalink / raw)
To: Dong, Eddie; +Cc: xen-ia64-devel, linux-ia64, kvm-ia64-devel, virtualization
On Tue, Feb 26, 2008 at 02:36:51AM +0800, Dong, Eddie wrote:
>
> > IA64 pv_ops frame work doesn't exist yet so that xen code does
> > in order to boot on both native and xen for now.
> > I expect those check will be eliminated during developing ia64 pv_ops.
>
> Qing He & I am working on the pv_ops framework, hopefully we can get
> a draft soon :)
Great!
What I am aware of at this moment is,
(some of the following can be covered by machine vector, though.)
- early setup before start_kernel()
Currently early_xen_setup() is directly called.
Eventually extending ia64 boot protocol would be necessary, though.
- Initialization hooks
struct pv_init_ops?
void (*arch_setup_early)(void)
void (*banner);
void (*pre_pasing_init)(void);
void (*post_pasing_init)(void);
void (*post_allocator_init)(void);
- irq hooks
struct pv_irq_ops
- init_IRQ(), irq_init()
- registering chip type
register_intr()
- assign_irq_vector()
- free_irq_vector()
- register_percpu_irq()
- send_ipi()
- resend_irq()
- IOSAPIC hooks
struct pv_iosapic_ops
- iosapic_init()
- iosapic_read()
- iosapic_write()
--
yamahata
^ permalink raw reply [flat|nested] 45+ messages in thread
end of thread, other threads:[~2008-02-26 1:44 UTC | newest]
Thread overview: 45+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20080221091731.641745000@ls.local.valinux.co.jp>
2008-02-21 9:17 ` [PATCH 01/28] ia64/xen: introduce ia64_set_rr0_to_rr4() to make kernel paravirtualization friendly yamahata
2008-02-21 9:17 ` [PATCH 02/28] ia64/xen: introduce ia64_get_psr_i() " yamahata
2008-02-21 9:17 ` [PATCH 03/28] ia64/xen: increase IA64_MAX_RSVD_REGIONS yamahata
2008-02-21 9:17 ` [PATCH 04/28] ia64/xen: introduce synch bitops which is necessary for ia64/xen support yamahata
2008-02-21 9:17 ` [PATCH 05/28] ia64/xen: import xen hypercall header file yamahata
2008-02-21 9:17 ` [PATCH 06/28] ia64/xen: define xen assembler constants which will be used later yamahata
2008-02-21 9:17 ` [PATCH 07/28] ia64/xen: detect xen environment at early boot time and do minimal initialization yamahata
2008-02-21 9:17 ` [PATCH 08/28] RFC: ia64/xen: xen hand written assembly code paravirtualization yamahata
2008-02-21 9:17 ` [PATCH 09/28] ia64/xen: paravirtualize pal_call_static() yamahata
2008-02-21 9:17 ` [PATCH 10/28] RFC: ia64/xen: introduce xen paravirtualized intrinsic operations for privileged instruction yamahata
2008-02-21 9:17 ` [PATCH 11/28] ia64: introduce basic facilities for binary patching yamahata
2008-02-21 9:17 ` [PATCH 12/28] RFC: ia64/xen: xen privileged instruction intrinsics " yamahata
2008-02-21 9:17 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU yamahata
2008-02-21 9:17 ` [PATCH 14/28] ia64/xen: ia64 domU part of xencomm yamahata
2008-02-21 9:17 ` [PATCH 15/28] ia64/xen: define xen_alloc_vm_area()/xen_free_vm_area() for ia64 arch yamahata
2008-02-21 9:17 ` [PATCH 16/28] ia64/xen: basic helper routines for xen/ia64 yamahata
2008-02-21 9:17 ` [PATCH 17/28] ia64/xen: domU initialization code yamahata
2008-02-21 9:17 ` [PATCH 18/28] ia64/xen: iosapic paravirtualization yamahata
2008-02-21 9:17 ` [PATCH 19/28] ia64/xen: xen domU irq chip introducing some helper functions, xen_send_ipi yamahata
2008-02-21 9:17 ` [PATCH 20/28] ia64/xen: domU xen machine vector without dma api yamahata
2008-02-21 9:17 ` [PATCH 21/28] ia64/xen: define xen related address conversion helper functions for domU yamahata
2008-02-21 9:17 ` [PATCH 22/28] ia64/xen: mca paravirtualization yamahata
2008-02-21 9:17 ` [PATCH 23/28] ia64/xen: sal paravirtualization yamahata
2008-02-21 9:17 ` [PATCH 24/28] ia64/xen: time paravirtualization yamahata
2008-02-21 9:17 ` [PATCH 25/28] ia64/xen: gate page paravirtualization yamahata
2008-02-21 9:17 ` [PATCH 26/28] ia64/xen: fsys paravirtualization yamahata
2008-02-21 9:17 ` [PATCH 27/28] ia64/xen: update Kconfig to allow xen domU Linux yamahata
2008-02-21 9:17 ` [PATCH 28/28] ia64/xen: add ia64/xen domU config yamahata
[not found] ` <20080221091904.811793000@ls.local.valinux.co.jp>
2008-02-21 23:08 ` [PATCH 20/28] ia64/xen: domU xen machine vector without dma api Jeremy Fitzhardinge
[not found] ` <20080221091906.007909000@ls.local.valinux.co.jp>
2008-02-21 23:11 ` [PATCH 24/28] ia64/xen: time paravirtualization Jeremy Fitzhardinge
2008-02-22 3:57 ` Isaku Yamahata
2008-02-22 3:57 ` Isaku Yamahata
2008-02-22 5:10 ` Isaku Yamahata
2008-02-21 23:11 ` Jeremy Fitzhardinge
[not found] ` <20080221091904.517166000@ls.local.valinux.co.jp>
2008-02-21 23:22 ` [PATCH 19/28] ia64/xen: xen domU irq chip introducing some helper functions, xen_send_ipi Jeremy Fitzhardinge
[not found] ` <20080221091905.122606000@ls.local.valinux.co.jp>
2008-02-21 23:45 ` [PATCH 21/28] ia64/xen: define xen related address conversion helper functions for domU Jeremy Fitzhardinge
[not found] ` <20080221091902.716789000@ls.local.valinux.co.jp>
2008-02-21 23:47 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary " Jeremy Fitzhardinge
2008-02-21 23:47 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary Jeremy Fitzhardinge
2008-02-22 3:54 ` [PATCH 13/28] ia64/xen: introduce xen hypercall routines necessary for domU Isaku Yamahata
2008-02-22 3:54 ` Isaku Yamahata
2008-02-25 18:36 ` [kvm-ia64-devel] [PATCH 13/28] ia64/xen: introduce xenhypercall " Dong, Eddie
2008-02-26 1:44 ` Isaku Yamahata
2008-02-26 1:44 ` Isaku Yamahata
2008-02-25 18:36 ` Dong, Eddie
2008-02-22 5:10 ` [PATCH 13/28] ia64/xen: introduce xen hypercall " Isaku Yamahata
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.