aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--buildconfigs/linux-defconfig_xen0_ia648
-rw-r--r--buildconfigs/linux-defconfig_xenU_ia648
-rw-r--r--buildconfigs/linux-defconfig_xen_ia648
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/Kconfig14
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/kernel/Makefile62
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S1
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/kernel/setup.c4
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/xen/Makefile3
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c361
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/xen/util.c2
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c273
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c319
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c600
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c258
-rw-r--r--linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S21
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c13
-rw-r--r--linux-2.6-xen-sparse/include/asm-ia64/hypercall.h176
-rw-r--r--linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h11
-rw-r--r--linux-2.6-xen-sparse/include/asm-ia64/maddr.h15
-rw-r--r--linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h3
-rw-r--r--linux-2.6-xen-sparse/include/asm-ia64/xen/xcom_hcall.h76
-rw-r--r--linux-2.6-xen-sparse/include/asm-ia64/xen/xencomm.h60
-rw-r--r--linux-2.6-xen-sparse/lib/Makefile2
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_restore.c3
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_save.c3
-rw-r--r--unmodified_drivers/linux-2.6/mkbuildtree5
-rw-r--r--unmodified_drivers/linux-2.6/platform-pci/Kbuild5
-rw-r--r--unmodified_drivers/linux-2.6/platform-pci/platform-pci.c7
-rw-r--r--xen/arch/ia64/Rules.mk20
-rw-r--r--xen/arch/ia64/asm-offsets.c3
-rw-r--r--xen/arch/ia64/linux-xen/entry.S6
-rw-r--r--xen/arch/ia64/linux-xen/mca.c2
-rw-r--r--xen/arch/ia64/linux-xen/sal.c75
-rw-r--r--xen/arch/ia64/linux-xen/tlb.c9
-rw-r--r--xen/arch/ia64/linux-xen/unaligned.c18
-rw-r--r--xen/arch/ia64/tools/p2m_expose/Makefile28
-rw-r--r--xen/arch/ia64/tools/p2m_expose/README.p2m_expose12
-rw-r--r--xen/arch/ia64/tools/p2m_expose/expose_p2m.c185
-rw-r--r--xen/arch/ia64/vmx/Makefile1
-rw-r--r--xen/arch/ia64/vmx/mm.c153
-rw-r--r--xen/arch/ia64/vmx/mmio.c12
-rw-r--r--xen/arch/ia64/vmx/optvfault.S596
-rw-r--r--xen/arch/ia64/vmx/pal_emul.c513
-rw-r--r--xen/arch/ia64/vmx/vlsapic.c169
-rw-r--r--xen/arch/ia64/vmx/vmmu.c98
-rw-r--r--xen/arch/ia64/vmx/vmx_entry.S2
-rw-r--r--xen/arch/ia64/vmx/vmx_init.c3
-rw-r--r--xen/arch/ia64/vmx/vmx_interrupt.c19
-rw-r--r--xen/arch/ia64/vmx/vmx_ivt.S10
-rw-r--r--xen/arch/ia64/vmx/vmx_phy_mode.c51
-rw-r--r--xen/arch/ia64/vmx/vmx_process.c220
-rw-r--r--xen/arch/ia64/vmx/vmx_vcpu.c62
-rw-r--r--xen/arch/ia64/vmx/vmx_virt.c30
-rw-r--r--xen/arch/ia64/vmx/vtlb.c8
-rw-r--r--xen/arch/ia64/xen/Makefile4
-rw-r--r--xen/arch/ia64/xen/dom0_ops.c5
-rw-r--r--xen/arch/ia64/xen/domain.c142
-rw-r--r--xen/arch/ia64/xen/faults.c14
-rw-r--r--xen/arch/ia64/xen/flushtlb.c117
-rw-r--r--xen/arch/ia64/xen/fw_emul.c67
-rw-r--r--xen/arch/ia64/xen/hypercall.c91
-rw-r--r--xen/arch/ia64/xen/mm.c259
-rw-r--r--xen/arch/ia64/xen/privop.c840
-rw-r--r--xen/arch/ia64/xen/regionreg.c4
-rw-r--r--xen/arch/ia64/xen/tlb_track.c506
-rw-r--r--xen/arch/ia64/xen/vcpu.c1637
-rw-r--r--xen/arch/ia64/xen/vhpt.c313
-rw-r--r--xen/arch/ia64/xen/xen.lds.S3
-rw-r--r--xen/arch/ia64/xen/xenasm.S28
-rw-r--r--xen/arch/ia64/xen/xencomm.c380
-rw-r--r--xen/arch/ia64/xen/xenmem.c93
-rw-r--r--xen/arch/ia64/xen/xenpatch.c122
-rw-r--r--xen/arch/ia64/xen/xensetup.c25
-rw-r--r--xen/arch/ia64/xen/xentime.c43
-rw-r--r--xen/include/asm-ia64/dom_fw.h9
-rw-r--r--xen/include/asm-ia64/domain.h58
-rw-r--r--xen/include/asm-ia64/flushtlb.h89
-rw-r--r--xen/include/asm-ia64/guest_access.h140
-rw-r--r--xen/include/asm-ia64/ia64_int.h4
-rw-r--r--xen/include/asm-ia64/linux-xen/asm/cache.h2
-rw-r--r--xen/include/asm-ia64/linux-xen/asm/pgtable.h34
-rw-r--r--xen/include/asm-ia64/linux-xen/asm/processor.h18
-rw-r--r--xen/include/asm-ia64/linux-xen/asm/system.h1
-rw-r--r--xen/include/asm-ia64/linux/README.origin1
-rw-r--r--xen/include/asm-ia64/linux/asm/sal.h10
-rw-r--r--xen/include/asm-ia64/linux/hash.h58
-rw-r--r--xen/include/asm-ia64/mm.h20
-rw-r--r--xen/include/asm-ia64/p2m_entry.h76
-rw-r--r--xen/include/asm-ia64/perfc_defn.h65
-rw-r--r--xen/include/asm-ia64/privop.h4
-rw-r--r--xen/include/asm-ia64/tlb_track.h155
-rw-r--r--xen/include/asm-ia64/tlbflush.h10
-rw-r--r--xen/include/asm-ia64/uaccess.h18
-rw-r--r--xen/include/asm-ia64/vcpu.h293
-rw-r--r--xen/include/asm-ia64/vcpumask.h60
-rw-r--r--xen/include/asm-ia64/vhpt.h43
-rw-r--r--xen/include/asm-ia64/vmx.h1
-rw-r--r--xen/include/asm-ia64/vmx_pal_vsa.h7
-rw-r--r--xen/include/asm-ia64/vmx_phy_mode.h7
-rw-r--r--xen/include/asm-ia64/vmx_uaccess.h156
-rw-r--r--xen/include/asm-ia64/vmx_vcpu.h597
-rw-r--r--xen/include/asm-ia64/xenkregs.h3
-rw-r--r--xen/include/asm-ia64/xensystem.h1
-rw-r--r--xen/include/public/arch-ia64.h83
104 files changed, 7909 insertions, 3433 deletions
diff --git a/buildconfigs/linux-defconfig_xen0_ia64 b/buildconfigs/linux-defconfig_xen0_ia64
index 36b3dfc36e..400fbdc3c1 100644
--- a/buildconfigs/linux-defconfig_xen0_ia64
+++ b/buildconfigs/linux-defconfig_xen0_ia64
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16.13-xen0
-# Fri Sep 1 11:03:26 2006
+# Linux kernel version: 2.6.16.29-xen0
+# Wed Oct 4 12:54:36 2006
#
#
@@ -92,6 +92,8 @@ CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
CONFIG_XEN=y
CONFIG_XEN_IA64_VDSO_PARAVIRT=y
+CONFIG_XEN_IA64_EXPOSE_P2M=y
+CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_DMA_IS_DMA32=y
# CONFIG_IA64_GENERIC is not set
@@ -119,6 +121,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_SMP=y
CONFIG_NR_CPUS=16
CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -1041,7 +1044,6 @@ CONFIG_SND_ATIIXP=y
# CONFIG_SND_ES1968 is not set
CONFIG_SND_FM801=y
# CONFIG_SND_FM801_TEA575X_BOOL is not set
-CONFIG_SND_FM801_TEA575X=y
# CONFIG_SND_HDA_INTEL is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
diff --git a/buildconfigs/linux-defconfig_xenU_ia64 b/buildconfigs/linux-defconfig_xenU_ia64
index da7f4e694d..a7e15190ee 100644
--- a/buildconfigs/linux-defconfig_xenU_ia64
+++ b/buildconfigs/linux-defconfig_xenU_ia64
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16.13-xenU
-# Fri Sep 1 10:50:54 2006
+# Linux kernel version: 2.6.16.29-xenU
+# Wed Oct 4 12:54:26 2006
#
#
@@ -89,6 +89,8 @@ CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
CONFIG_XEN=y
CONFIG_XEN_IA64_VDSO_PARAVIRT=y
+CONFIG_XEN_IA64_EXPOSE_P2M=y
+CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_DMA_IS_DMA32=y
# CONFIG_IA64_GENERIC is not set
@@ -116,6 +118,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_SMP=y
CONFIG_NR_CPUS=16
# CONFIG_HOTPLUG_CPU is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -940,7 +943,6 @@ CONFIG_SND_AC97_BUS=y
# CONFIG_SND_ES1968 is not set
CONFIG_SND_FM801=y
# CONFIG_SND_FM801_TEA575X_BOOL is not set
-CONFIG_SND_FM801_TEA575X=y
# CONFIG_SND_HDA_INTEL is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
diff --git a/buildconfigs/linux-defconfig_xen_ia64 b/buildconfigs/linux-defconfig_xen_ia64
index a614cd9b8f..085d165ea7 100644
--- a/buildconfigs/linux-defconfig_xen_ia64
+++ b/buildconfigs/linux-defconfig_xen_ia64
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16.13-xen
-# Fri Sep 1 10:58:55 2006
+# Linux kernel version: 2.6.16.29-xen
+# Wed Oct 4 12:31:45 2006
#
#
@@ -92,6 +92,8 @@ CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
CONFIG_XEN=y
CONFIG_XEN_IA64_VDSO_PARAVIRT=y
+CONFIG_XEN_IA64_EXPOSE_P2M=y
+CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_DMA_IS_DMA32=y
# CONFIG_IA64_GENERIC is not set
@@ -119,6 +121,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_SMP=y
CONFIG_NR_CPUS=16
CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -1047,7 +1050,6 @@ CONFIG_SND_ATIIXP=y
# CONFIG_SND_ES1968 is not set
CONFIG_SND_FM801=y
# CONFIG_SND_FM801_TEA575X_BOOL is not set
-CONFIG_SND_FM801_TEA575X=y
# CONFIG_SND_HDA_INTEL is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
diff --git a/linux-2.6-xen-sparse/arch/ia64/Kconfig b/linux-2.6-xen-sparse/arch/ia64/Kconfig
index 78f5e2b3e3..4073a04638 100644
--- a/linux-2.6-xen-sparse/arch/ia64/Kconfig
+++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig
@@ -64,6 +64,20 @@ config XEN_IA64_VDSO_PARAVIRT
help
vDSO paravirtualization
+config XEN_IA64_EXPOSE_P2M
+ bool "Xen/IA64 exposure p2m table"
+ depends on XEN
+ default y
+ help
+ expose p2m from xen
+
+config XEN_IA64_EXPOSE_P2M_USE_DTR
+ bool "Xen/IA64 map p2m table with dtr"
+ depends on XEN_IA64_EXPOSE_P2M
+ default y
+ help
+ use dtr to map the exposed p2m table
+
config SCHED_NO_NO_OMIT_FRAME_POINTER
bool
default y
diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/Makefile b/linux-2.6-xen-sparse/arch/ia64/kernel/Makefile
new file mode 100644
index 0000000000..003e9ee600
--- /dev/null
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/Makefile
@@ -0,0 +1,62 @@
+#
+# Makefile for the linux kernel.
+#
+
+extra-y := head.o init_task.o vmlinux.lds
+
+obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \
+ irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
+ salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o \
+ unwind.o mca.o mca_asm.o topology.o
+
+obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o
+obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o
+obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o
+obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o
+
+ifneq ($(CONFIG_ACPI_PROCESSOR),)
+obj-y += acpi-processor.o
+endif
+
+obj-$(CONFIG_IA64_PALINFO) += palinfo.o
+obj-$(CONFIG_IOSAPIC) += iosapic.o
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_SMP) += smp.o smpboot.o
+obj-$(CONFIG_NUMA) += numa.o
+obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o
+obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq/
+obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
+obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
+obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
+mca_recovery-y += mca_drv.o mca_drv_asm.o
+
+# The gate DSO image is built using a special linker script.
+targets += gate.so gate-syms.o
+
+extra-y += gate.so gate-syms.o gate.lds gate.o
+
+# fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
+CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31
+
+CPPFLAGS_gate.lds := -P -C -U$(ARCH)
+
+quiet_cmd_gate = GATE $@
+ cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@
+
+GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \
+ $(call ld-option, -Wl$(comma)--hash-style=sysv)
+$(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE
+ $(call if_changed,gate)
+
+$(obj)/built-in.o: $(obj)/gate-syms.o
+$(obj)/built-in.o: ld_flags += -R $(obj)/gate-syms.o
+
+GATECFLAGS_gate-syms.o = -r
+$(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE
+ $(call if_changed,gate)
+
+# gate-data.o contains the gate DSO image as data in section .data.gate.
+# 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
diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S b/linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S
index 5f0163f0be..45377beaa4 100644
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/gate.lds.S
@@ -13,6 +13,7 @@ SECTIONS
. = GATE_ADDR + SIZEOF_HEADERS;
.hash : { *(.hash) } :readable
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
index f792900cf9..8f15b3001c 100644
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
@@ -63,6 +63,7 @@
#include <asm/system.h>
#ifdef CONFIG_XEN
#include <asm/hypervisor.h>
+#include <asm/xen/xencomm.h>
#endif
#include <linux/dma-mapping.h>
@@ -433,6 +434,9 @@ setup_arch (char **cmdline_p)
#ifdef CONFIG_XEN
if (is_running_on_xen()) {
+ /* Must be done before any hypercall. */
+ xencomm_init();
+
setup_xen_features();
/* Register a call for panic conditions. */
notifier_chain_register(&panic_notifier_list, &xen_panic_block);
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/Makefile b/linux-2.6-xen-sparse/arch/ia64/xen/Makefile
index c2b4f94edd..36434aac72 100644
--- a/linux-2.6-xen-sparse/arch/ia64/xen/Makefile
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/Makefile
@@ -3,6 +3,7 @@
#
obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o \
- hypervisor.o pci-dma-xen.o util.o
+ hypervisor.o pci-dma-xen.o util.o xencomm.o xcom_hcall.o \
+ xcom_mini.o xcom_privcmd.o
pci-dma-xen-y := ../../i386/kernel/pci-dma-xen.o
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
index 93de465364..2a85caa0d5 100644
--- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
@@ -40,59 +40,11 @@ EXPORT_SYMBOL(xen_start_info);
int running_on_xen;
EXPORT_SYMBOL(running_on_xen);
-//XXX xen/ia64 copy_from_guest() is broken.
-// This is a temporal work around until it is fixed.
-// used by balloon.c netfront.c
-
-// get_xen_guest_handle is defined only when __XEN_TOOLS__ is defined
-// if the definition in arch-ia64.h is changed, this must be updated.
-#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
-
-int
-ia64_xenmem_reservation_op(unsigned long op,
- struct xen_memory_reservation* reservation__)
-{
- struct xen_memory_reservation reservation = *reservation__;
- unsigned long* frame_list;
- unsigned long nr_extents = reservation__->nr_extents;
- int ret = 0;
- get_xen_guest_handle(frame_list, reservation__->extent_start);
-
- BUG_ON(op != XENMEM_increase_reservation &&
- op != XENMEM_decrease_reservation &&
- op != XENMEM_populate_physmap);
-
- while (nr_extents > 0) {
- int tmp_ret;
- volatile unsigned long dummy;
-
- set_xen_guest_handle(reservation.extent_start, frame_list);
- reservation.nr_extents = nr_extents;
-
- dummy = frame_list[0];// re-install tlb entry before hypercall
- tmp_ret = ____HYPERVISOR_memory_op(op, &reservation);
- if (tmp_ret < 0) {
- if (ret == 0) {
- ret = tmp_ret;
- }
- break;
- }
- if (tmp_ret == 0) {
- //XXX dirty work around for skbuff_ctor()
- // of a non-privileged domain,
- if ((op == XENMEM_increase_reservation ||
- op == XENMEM_populate_physmap) &&
- !is_initial_xendomain() &&
- reservation.extent_order > 0)
- return ret;
- }
- frame_list += tmp_ret;
- nr_extents -= tmp_ret;
- ret += tmp_ret;
- }
- return ret;
-}
-EXPORT_SYMBOL(ia64_xenmem_reservation_op);
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
+static int p2m_expose_init(void);
+#else
+#define p2m_expose_init() (-ENOSYS)
+#endif
//XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear()
// move those to lib/contiguous_bitmap?
@@ -371,8 +323,6 @@ gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop)
int
HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
{
- __u64 va1, va2, pa1, pa2;
-
if (cmd == GNTTABOP_map_grant_ref) {
unsigned int i;
for (i = 0; i < count; i++) {
@@ -380,29 +330,7 @@ HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
(struct gnttab_map_grant_ref*)uop + i);
}
}
- va1 = (__u64)uop & PAGE_MASK;
- pa1 = pa2 = 0;
- if ((REGION_NUMBER(va1) == 5) &&
- ((va1 - KERNEL_START) >= KERNEL_TR_PAGE_SIZE)) {
- pa1 = ia64_tpa(va1);
- if (cmd <= GNTTABOP_transfer) {
- static uint32_t uop_size[GNTTABOP_transfer + 1] = {
- sizeof(struct gnttab_map_grant_ref),
- sizeof(struct gnttab_unmap_grant_ref),
- sizeof(struct gnttab_setup_table),
- sizeof(struct gnttab_dump_table),
- sizeof(struct gnttab_transfer),
- };
- va2 = (__u64)uop + (uop_size[cmd] * count) - 1;
- va2 &= PAGE_MASK;
- if (va1 != va2) {
- /* maximum size of uop is 2pages */
- BUG_ON(va2 > va1 + PAGE_SIZE);
- pa2 = ia64_tpa(va2);
- }
- }
- }
- return ____HYPERVISOR_grant_table_op(cmd, uop, count, pa1, pa2);
+ return xencomm_mini_hypercall_grant_table_op(cmd, uop, count);
}
EXPORT_SYMBOL(HYPERVISOR_grant_table_op);
@@ -526,6 +454,10 @@ out:
privcmd_resource_min, privcmd_resource_max,
(privcmd_resource_max - privcmd_resource_min) >> 20);
BUG_ON(privcmd_resource_min >= privcmd_resource_max);
+
+ // XXX this should be somewhere appropriate
+ (void)p2m_expose_init();
+
return 0;
}
late_initcall(xen_ia64_privcmd_init);
@@ -845,3 +777,276 @@ time_resume(void)
/* Just trigger a tick. */
ia64_cpu_local_tick();
}
+
+///////////////////////////////////////////////////////////////////////////
+// expose p2m table
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
+#include <linux/cpu.h>
+#include <asm/uaccess.h>
+
+int p2m_initialized __read_mostly = 0;
+
+unsigned long p2m_min_low_pfn __read_mostly;
+unsigned long p2m_max_low_pfn __read_mostly;
+unsigned long p2m_convert_min_pfn __read_mostly;
+unsigned long p2m_convert_max_pfn __read_mostly;
+
+static struct resource p2m_resource = {
+ .name = "Xen p2m table",
+ .flags = IORESOURCE_MEM,
+};
+static unsigned long p2m_assign_start_pfn __read_mostly;
+static unsigned long p2m_assign_end_pfn __read_mostly;
+volatile const pte_t* p2m_pte __read_mostly;
+
+#define GRNULE_PFN PTRS_PER_PTE
+static unsigned long p2m_granule_pfn __read_mostly = GRNULE_PFN;
+
+#define ROUNDDOWN(x, y) ((x) & ~((y) - 1))
+#define ROUNDUP(x, y) (((x) + (y) - 1) & ~((y) - 1))
+
+#define P2M_PREFIX "Xen p2m: "
+
+static int xen_ia64_p2m_expose __read_mostly = 1;
+module_param(xen_ia64_p2m_expose, int, 0);
+MODULE_PARM_DESC(xen_ia64_p2m_expose,
+ "enable/disable xen/ia64 p2m exposure optimization\n");
+
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+static int xen_ia64_p2m_expose_use_dtr __read_mostly = 1;
+module_param(xen_ia64_p2m_expose_use_dtr, int, 0);
+MODULE_PARM_DESC(xen_ia64_p2m_expose_use_dtr,
+ "use/unuse dtr to map exposed p2m table\n");
+
+static const int p2m_page_shifts[] = {
+ _PAGE_SIZE_4K,
+ _PAGE_SIZE_8K,
+ _PAGE_SIZE_16K,
+ _PAGE_SIZE_64K,
+ _PAGE_SIZE_256K,
+ _PAGE_SIZE_1M,
+ _PAGE_SIZE_4M,
+ _PAGE_SIZE_16M,
+ _PAGE_SIZE_64M,
+ _PAGE_SIZE_256M,
+};
+
+struct p2m_itr_arg {
+ unsigned long vaddr;
+ unsigned long pteval;
+ unsigned long log_page_size;
+};
+static struct p2m_itr_arg p2m_itr_arg __read_mostly;
+
+// This should be in asm-ia64/kregs.h
+#define IA64_TR_P2M_TABLE 3
+
+static void
+p2m_itr(void* info)
+{
+ struct p2m_itr_arg* arg = (struct p2m_itr_arg*)info;
+ ia64_itr(0x2, IA64_TR_P2M_TABLE,
+ arg->vaddr, arg->pteval, arg->log_page_size);
+ ia64_srlz_d();
+}
+
+static int
+p2m_expose_dtr_call(struct notifier_block *self,
+ unsigned long event, void* ptr)
+{
+ unsigned int cpu = (unsigned int)(long)ptr;
+ if (event != CPU_ONLINE)
+ return 0;
+ if (!(p2m_initialized && xen_ia64_p2m_expose_use_dtr))
+ smp_call_function_single(cpu, &p2m_itr, &p2m_itr_arg, 1, 1);
+ return 0;
+}
+
+static struct notifier_block p2m_expose_dtr_hotplug_notifier = {
+ .notifier_call = p2m_expose_dtr_call,
+ .next = NULL,
+ .priority = 0
+};
+#endif
+
+static int
+p2m_expose_init(void)
+{
+ unsigned long num_pfn;
+ unsigned long size = 0;
+ unsigned long p2m_size = 0;
+ unsigned long align = ~0UL;
+ int error = 0;
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+ int i;
+ unsigned long page_size;
+ unsigned long log_page_size = 0;
+#endif
+
+ if (!xen_ia64_p2m_expose)
+ return -ENOSYS;
+ if (p2m_initialized)
+ return 0;
+
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+ error = register_cpu_notifier(&p2m_expose_dtr_hotplug_notifier);
+ if (error < 0)
+ return error;
+#endif
+
+ lock_cpu_hotplug();
+ if (p2m_initialized)
+ goto out;
+
+#ifdef CONFIG_DISCONTIGMEM
+ p2m_min_low_pfn = min_low_pfn;
+ p2m_max_low_pfn = max_low_pfn;
+#else
+ p2m_min_low_pfn = 0;
+ p2m_max_low_pfn = max_pfn;
+#endif
+
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+ if (xen_ia64_p2m_expose_use_dtr) {
+ unsigned long granule_pfn = 0;
+ p2m_size = p2m_max_low_pfn - p2m_min_low_pfn;
+ for (i = 0;
+ i < sizeof(p2m_page_shifts)/sizeof(p2m_page_shifts[0]);
+ i++) {
+ log_page_size = p2m_page_shifts[i];
+ page_size = 1UL << log_page_size;
+ if (page_size < p2m_size)
+ continue;
+
+ granule_pfn = max(page_size >> PAGE_SHIFT,
+ p2m_granule_pfn);
+ p2m_convert_min_pfn = ROUNDDOWN(p2m_min_low_pfn,
+ granule_pfn);
+ p2m_convert_max_pfn = ROUNDUP(p2m_max_low_pfn,
+ granule_pfn);
+ num_pfn = p2m_convert_max_pfn - p2m_convert_min_pfn;
+ size = num_pfn << PAGE_SHIFT;
+ p2m_size = num_pfn / PTRS_PER_PTE;
+ p2m_size = ROUNDUP(p2m_size, granule_pfn << PAGE_SHIFT);
+ if (p2m_size == page_size)
+ break;
+ }
+ if (p2m_size != page_size) {
+ printk(KERN_ERR "p2m_size != page_size\n");
+ error = -EINVAL;
+ goto out;
+ }
+ align = max(privcmd_resource_align, granule_pfn << PAGE_SHIFT);
+ } else
+#endif
+ {
+ BUG_ON(p2m_granule_pfn & (p2m_granule_pfn - 1));
+ p2m_convert_min_pfn = ROUNDDOWN(p2m_min_low_pfn,
+ p2m_granule_pfn);
+ p2m_convert_max_pfn = ROUNDUP(p2m_max_low_pfn, p2m_granule_pfn);
+ num_pfn = p2m_convert_max_pfn - p2m_convert_min_pfn;
+ size = num_pfn << PAGE_SHIFT;
+ p2m_size = num_pfn / PTRS_PER_PTE;
+ p2m_size = ROUNDUP(p2m_size, p2m_granule_pfn << PAGE_SHIFT);
+ align = max(privcmd_resource_align,
+ p2m_granule_pfn << PAGE_SHIFT);
+ }
+
+ // use privcmd region
+ error = allocate_resource(&iomem_resource, &p2m_resource, p2m_size,
+ privcmd_resource_min, privcmd_resource_max,
+ align, NULL, NULL);
+ if (error) {
+ printk(KERN_ERR P2M_PREFIX
+ "can't allocate region for p2m exposure "
+ "[0x%016lx, 0x%016lx) 0x%016lx\n",
+ p2m_convert_min_pfn, p2m_convert_max_pfn, p2m_size);
+ goto out;
+ }
+
+ p2m_assign_start_pfn = p2m_resource.start >> PAGE_SHIFT;
+ p2m_assign_end_pfn = p2m_resource.end >> PAGE_SHIFT;
+
+ error = HYPERVISOR_expose_p2m(p2m_convert_min_pfn,
+ p2m_assign_start_pfn,
+ size, p2m_granule_pfn);
+ if (error) {
+ printk(KERN_ERR P2M_PREFIX "failed expose p2m hypercall %d\n",
+ error);
+ printk(KERN_ERR P2M_PREFIX "conv 0x%016lx assign 0x%016lx "
+ "size 0x%016lx granule 0x%016lx\n",
+ p2m_convert_min_pfn, p2m_assign_start_pfn,
+ size, p2m_granule_pfn);;
+ release_resource(&p2m_resource);
+ goto out;
+ }
+ p2m_pte = (volatile const pte_t*)pfn_to_kaddr(p2m_assign_start_pfn);
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+ if (xen_ia64_p2m_expose_use_dtr) {
+ p2m_itr_arg.vaddr = (unsigned long)__va(p2m_assign_start_pfn
+ << PAGE_SHIFT);
+ p2m_itr_arg.pteval = pte_val(pfn_pte(p2m_assign_start_pfn,
+ PAGE_KERNEL));
+ p2m_itr_arg.log_page_size = log_page_size;
+ smp_mb();
+ smp_call_function(&p2m_itr, &p2m_itr_arg, 1, 1);
+ p2m_itr(&p2m_itr_arg);
+ }
+#endif
+ smp_mb();
+ p2m_initialized = 1;
+ printk(P2M_PREFIX "assign p2m table of [0x%016lx, 0x%016lx)\n",
+ p2m_convert_min_pfn << PAGE_SHIFT,
+ p2m_convert_max_pfn << PAGE_SHIFT);
+ printk(P2M_PREFIX "to [0x%016lx, 0x%016lx) (%ld KBytes)\n",
+ p2m_assign_start_pfn << PAGE_SHIFT,
+ p2m_assign_end_pfn << PAGE_SHIFT,
+ p2m_size / 1024);
+out:
+ unlock_cpu_hotplug();
+ return error;
+}
+
+#ifdef notyet
+void
+p2m_expose_cleanup(void)
+{
+ BUG_ON(!p2m_initialized);
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR
+ unregister_cpu_notifier(&p2m_expose_dtr_hotplug_notifier);
+#endif
+ release_resource(&p2m_resource);
+}
+#endif
+
+//XXX inlinize?
+unsigned long
+p2m_phystomach(unsigned long gpfn)
+{
+ volatile const pte_t* pte;
+ unsigned long mfn;
+ unsigned long pteval;
+
+ if (!p2m_initialized ||
+ gpfn < p2m_min_low_pfn || gpfn > p2m_max_low_pfn
+ /* || !pfn_valid(gpfn) */)
+ return INVALID_MFN;
+ pte = p2m_pte + (gpfn - p2m_convert_min_pfn);
+
+ mfn = INVALID_MFN;
+ if (likely(__get_user(pteval, (unsigned long __user *)pte) == 0 &&
+ pte_present(__pte(pteval)) &&
+ pte_pfn(__pte(pteval)) != (INVALID_MFN >> PAGE_SHIFT)))
+ mfn = (pteval & _PFN_MASK) >> PAGE_SHIFT;
+
+ return mfn;
+}
+
+EXPORT_SYMBOL_GPL(p2m_initialized);
+EXPORT_SYMBOL_GPL(p2m_min_low_pfn);
+EXPORT_SYMBOL_GPL(p2m_max_low_pfn);
+EXPORT_SYMBOL_GPL(p2m_convert_min_pfn);
+EXPORT_SYMBOL_GPL(p2m_convert_max_pfn);
+EXPORT_SYMBOL_GPL(p2m_pte);
+EXPORT_SYMBOL_GPL(p2m_phystomach);
+#endif
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/util.c b/linux-2.6-xen-sparse/arch/ia64/xen/util.c
index 02dfaabc66..7df0c5f72c 100644
--- a/linux-2.6-xen-sparse/arch/ia64/xen/util.c
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/util.c
@@ -28,6 +28,8 @@
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
#include <xen/driver_util.h>
+#include <xen/interface/memory.h>
+#include <asm/hypercall.h>
struct vm_struct *alloc_vm_area(unsigned long size)
{
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c
new file mode 100644
index 0000000000..01842ba34a
--- /dev/null
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c
@@ -0,0 +1,273 @@
+/*
+ * 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>
+ */
+#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/dom0_ops.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/acm_ops.h>
+#include <xen/interface/hvm/params.h>
+#include <asm/hypercall.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 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/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 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_create_inline(str));
+}
+
+int
+xencomm_hypercall_event_channel_op(int cmd, void *op)
+{
+ return xencomm_arch_hypercall_event_channel_op
+ (cmd, xencomm_create_inline(op));
+}
+
+int
+xencomm_hypercall_xen_version(int cmd, void *arg)
+{
+ switch (cmd) {
+ case XENVER_version:
+ case XENVER_extraversion:
+ case XENVER_compile_info:
+ case XENVER_capabilities:
+ case XENVER_changeset:
+ case XENVER_platform_parameters:
+ case XENVER_pagesize:
+ case XENVER_get_features:
+ break;
+ default:
+ printk("%s: unknown version cmd %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_xen_version
+ (cmd, xencomm_create_inline(arg));
+}
+
+int
+xencomm_hypercall_physdev_op(int cmd, void *op)
+{
+ return xencomm_arch_hypercall_physdev_op
+ (cmd, xencomm_create_inline(op));
+}
+
+static void *
+xencommize_grant_table_op(unsigned int cmd, void *op, unsigned int count)
+{
+ switch (cmd) {
+ case GNTTABOP_map_grant_ref:
+ case GNTTABOP_unmap_grant_ref:
+ break;
+ case GNTTABOP_setup_table:
+ {
+ struct gnttab_setup_table *setup = op;
+ struct xencomm_handle *frame_list;
+
+ frame_list = xencomm_create_inline
+ (xen_guest_handle(setup->frame_list));
+
+ set_xen_guest_handle(setup->frame_list, (void *)frame_list);
+ break;
+ }
+ case GNTTABOP_dump_table:
+ case GNTTABOP_transfer:
+ case GNTTABOP_copy:
+ break;
+ default:
+ printk("%s: unknown grant table op %d\n", __func__, cmd);
+ BUG();
+ }
+
+ return xencomm_create_inline(op);
+}
+
+int
+xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, unsigned int count)
+{
+ void *desc = xencommize_grant_table_op (cmd, op, count);
+
+ return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
+}
+
+int
+xencomm_hypercall_sched_op(int cmd, void *arg)
+{
+ switch (cmd) {
+ case SCHEDOP_yield:
+ case SCHEDOP_block:
+ case SCHEDOP_shutdown:
+ case SCHEDOP_remote_shutdown:
+ break;
+ case SCHEDOP_poll:
+ {
+ sched_poll_t *poll = arg;
+ struct xencomm_handle *ports;
+
+ ports = xencomm_create_inline(xen_guest_handle(poll->ports));
+
+ set_xen_guest_handle(poll->ports, (void *)ports);
+ break;
+ }
+ default:
+ printk("%s: unknown sched op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_sched_op(cmd, xencomm_create_inline(arg));
+}
+
+int
+xencomm_hypercall_multicall(void *call_list, int nr_calls)
+{
+ int i;
+ multicall_entry_t *mce;
+
+ for (i = 0; i < nr_calls; i++) {
+ mce = (multicall_entry_t *)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:
+ mce->args[1] = (unsigned long)xencommize_grant_table_op
+ (mce->args[0], (void *)mce->args[1],
+ mce->args[2]);
+ break;
+ case __HYPERVISOR_memory_op:
+ default:
+ printk("%s: unhandled multicall op entry op %lu\n",
+ __func__, mce->op);
+ return -ENOSYS;
+ }
+ }
+
+ return xencomm_arch_hypercall_multicall
+ (xencomm_create_inline(call_list), nr_calls);
+}
+
+int
+xencomm_hypercall_callback_op(int cmd, void *arg)
+{
+ switch (cmd)
+ {
+ case CALLBACKOP_register:
+ case CALLBACKOP_unregister:
+ break;
+ default:
+ printk("%s: unknown callback op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_callback_op
+ (cmd, xencomm_create_inline(arg));
+}
+
+static void
+xencommize_memory_reservation (xen_memory_reservation_t *mop)
+{
+ struct xencomm_handle *desc;
+
+ desc = xencomm_create_inline(xen_guest_handle(mop->extent_start));
+ set_xen_guest_handle(mop->extent_start, (void *)desc);
+}
+
+int
+xencomm_hypercall_memory_op(unsigned int cmd, void *arg)
+{
+ switch (cmd) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ case XENMEM_populate_physmap:
+ xencommize_memory_reservation((xen_memory_reservation_t *)arg);
+ break;
+
+ case XENMEM_maximum_ram_page:
+ break;
+
+ case XENMEM_exchange:
+ xencommize_memory_reservation
+ (&((xen_memory_exchange_t *)arg)->in);
+ xencommize_memory_reservation
+ (&((xen_memory_exchange_t *)arg)->out);
+ break;
+
+ default:
+ printk("%s: unknown memory op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_memory_op
+ (cmd, xencomm_create_inline(arg));
+}
+
+unsigned long
+xencomm_hypercall_hvm_op(int cmd, void *arg)
+{
+ switch (cmd) {
+ case HVMOP_set_param:
+ case HVMOP_get_param:
+ break;
+ default:
+ printk("%s: unknown hvm op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return xencomm_arch_hypercall_hvm_op(cmd, xencomm_create_inline(arg));
+}
+
+int
+xencomm_hypercall_suspend(unsigned long srec)
+{
+ struct sched_shutdown arg;
+
+ arg.reason = SHUTDOWN_suspend;
+
+ return xencomm_arch_hypercall_suspend(xencomm_create_inline(&arg));
+}
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c
new file mode 100644
index 0000000000..5adec0c325
--- /dev/null
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c
@@ -0,0 +1,319 @@
+/*
+ * 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>
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/dom0_ops.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/xencomm.h>
+#include <xen/interface/version.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/hvm/params.h>
+#ifdef CONFIG_VMX_GUEST
+#include <asm/hypervisor.h>
+#else
+#include <asm/hypercall.h>
+#endif
+#include <asm/xen/xencomm.h>
+
+int
+xencomm_mini_hypercall_event_channel_op(int cmd, void *op)
+{
+ struct xencomm_mini xc_area[2];
+ int nbr_area = 2;
+ struct xencomm_handle *desc;
+ int rc;
+
+ rc = xencomm_create_mini(xc_area, &nbr_area,
+ op, sizeof(evtchn_op_t), &desc);
+ if (rc)
+ return rc;
+
+ return xencomm_arch_hypercall_event_channel_op(cmd, desc);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_event_channel_op);
+
+static int
+xencommize_mini_grant_table_op(struct xencomm_mini *xc_area, int *nbr_area,
+ unsigned int cmd, void *op, unsigned int count,
+ struct xencomm_handle **desc)
+{
+ struct xencomm_handle *desc1;
+ unsigned int argsize;
+ int rc;
+
+ 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;
+ rc = xencomm_create_mini
+ (xc_area, nbr_area,
+ xen_guest_handle(setup->frame_list),
+ setup->nr_frames
+ * sizeof(*xen_guest_handle(setup->frame_list)),
+ &desc1);
+ if (rc)
+ return rc;
+ 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;
+ default:
+ printk("%s: unknown mini grant table op %d\n", __func__, cmd);
+ BUG();
+ }
+
+ rc = xencomm_create_mini(xc_area, nbr_area, op, count * argsize, desc);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+int
+xencomm_mini_hypercall_grant_table_op(unsigned int cmd, void *op,
+ unsigned int count)
+{
+ int rc;
+ struct xencomm_handle *desc;
+ int nbr_area = 2;
+ struct xencomm_mini xc_area[2];
+
+ rc = xencommize_mini_grant_table_op(xc_area, &nbr_area,
+ cmd, op, count, &desc);
+ if (rc)
+ return rc;
+
+ return xencomm_arch_hypercall_grant_table_op(cmd, desc, count);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_grant_table_op);
+
+int
+xencomm_mini_hypercall_multicall(void *call_list, int nr_calls)
+{
+ int i;
+ multicall_entry_t *mce;
+ int nbr_area = 2 + nr_calls * 3;
+ struct xencomm_mini xc_area[nbr_area];
+ struct xencomm_handle *desc;
+ int rc;
+
+ for (i = 0; i < nr_calls; i++) {
+ mce = (multicall_entry_t *)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_mini_grant_table_op
+ (xc_area, &nbr_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("%s: unhandled multicall op entry op %lu\n",
+ __func__, mce->op);
+ return -ENOSYS;
+ }
+ }
+
+ rc = xencomm_create_mini(xc_area, &nbr_area, call_list,
+ nr_calls * sizeof(multicall_entry_t), &desc);
+ if (rc)
+ return rc;
+
+ return xencomm_arch_hypercall_multicall(desc, nr_calls);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_multicall);
+
+static int
+xencommize_mini_memory_reservation(struct xencomm_mini *area, int *nbr_area,
+ xen_memory_reservation_t *mop)
+{
+ struct xencomm_handle *desc;
+ int rc;
+
+ rc = xencomm_create_mini
+ (area, nbr_area,
+ xen_guest_handle(mop->extent_start),
+ mop->nr_extents
+ * sizeof(*xen_guest_handle(mop->extent_start)),
+ &desc);
+ if (rc)
+ return rc;
+
+ set_xen_guest_handle(mop->extent_start, (void *)desc);
+
+ return 0;
+}
+
+int
+xencomm_mini_hypercall_memory_op(unsigned int cmd, void *arg)
+{
+ int nbr_area = 4;
+ struct xencomm_mini xc_area[4];
+ struct xencomm_handle *desc;
+ int rc;
+ unsigned int argsize;
+
+ switch (cmd) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ case XENMEM_populate_physmap:
+ argsize = sizeof(xen_memory_reservation_t);
+ rc = xencommize_mini_memory_reservation
+ (xc_area, &nbr_area, (xen_memory_reservation_t *)arg);
+ if (rc)
+ return rc;
+ break;
+
+ case XENMEM_maximum_ram_page:
+ argsize = 0;
+ break;
+
+ case XENMEM_exchange:
+ argsize = sizeof(xen_memory_exchange_t);
+ rc = xencommize_mini_memory_reservation
+ (xc_area, &nbr_area,
+ &((xen_memory_exchange_t *)arg)->in);
+ if (rc)
+ return rc;
+ rc = xencommize_mini_memory_reservation
+ (xc_area, &nbr_area,
+ &((xen_memory_exchange_t *)arg)->out);
+ if (rc)
+ return rc;
+ break;
+
+ case XENMEM_add_to_physmap:
+ argsize = sizeof (xen_add_to_physmap_t);
+ break;
+
+ default:
+ printk("%s: unknown mini memory op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ rc = xencomm_create_mini(xc_area, &nbr_area, arg, argsize, &desc);
+ if (rc)
+ return rc;
+
+ return xencomm_arch_hypercall_memory_op(cmd, desc);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_memory_op);
+
+unsigned long
+xencomm_mini_hypercall_hvm_op(int cmd, void *arg)
+{
+ struct xencomm_handle *desc;
+ int nbr_area = 2;
+ struct xencomm_mini xc_area[2];
+ unsigned int argsize;
+ int rc;
+
+ switch (cmd) {
+ case HVMOP_get_param:
+ case HVMOP_set_param:
+ argsize = sizeof(xen_hvm_param_t);
+ break;
+ default:
+ printk("%s: unknown HVMOP %d\n", __func__, cmd);
+ return -EINVAL;
+ }
+
+ rc = xencomm_create_mini(xc_area, &nbr_area, arg, argsize, &desc);
+ if (rc)
+ return rc;
+
+ return xencomm_arch_hypercall_hvm_op(cmd, desc);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_hvm_op);
+
+int
+xencomm_mini_hypercall_xen_version(int cmd, void *arg)
+{
+ struct xencomm_handle *desc;
+ int nbr_area = 2;
+ struct xencomm_mini xc_area[2];
+ unsigned int argsize;
+ int rc;
+
+ switch (cmd) {
+ case XENVER_version:
+ /* do not actually pass an argument */
+ return xencomm_arch_hypercall_xen_version(cmd, 0);
+ case XENVER_extraversion:
+ argsize = sizeof(xen_extraversion_t);
+ break;
+ case XENVER_compile_info:
+ argsize = sizeof(xen_compile_info_t);
+ break;
+ case XENVER_capabilities:
+ argsize = sizeof(xen_capabilities_info_t);
+ break;
+ case XENVER_changeset:
+ argsize = sizeof(xen_changeset_info_t);
+ break;
+ case XENVER_platform_parameters:
+ argsize = sizeof(xen_platform_parameters_t);
+ break;
+ case XENVER_pagesize:
+ argsize = (arg == NULL) ? 0 : sizeof(void *);
+ break;
+ case XENVER_get_features:
+ argsize = (arg == NULL) ? 0 : sizeof(xen_feature_info_t);
+ break;
+
+ default:
+ printk("%s: unknown version op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ rc = xencomm_create_mini(xc_area, &nbr_area, arg, argsize, &desc);
+ if (rc)
+ return rc;
+
+ return xencomm_arch_hypercall_xen_version(cmd, desc);
+}
+EXPORT_SYMBOL(xencomm_mini_hypercall_xen_version);
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c
new file mode 100644
index 0000000000..c11fe1ec05
--- /dev/null
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c
@@ -0,0 +1,600 @@
+/*
+ * 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.
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ * Tristan Gingold <tristan.gingold@bull.net>
+ */
+#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/dom0_ops.h>
+#define __XEN__
+#include <xen/interface/domctl.h>
+#include <xen/interface/sysctl.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/version.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/acm_ops.h>
+#include <xen/interface/hvm/params.h>
+#include <xen/public/privcmd.h>
+#include <asm/hypercall.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/xen/xencomm.h>
+
+#define ROUND_DIV(v,s) (((v) + (s) - 1) / (s))
+
+static int
+xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall)
+{
+ dom0_op_t kern_op;
+ dom0_op_t __user *user_op = (dom0_op_t __user *)hypercall->arg[0];
+ struct xencomm_handle *op_desc;
+ struct xencomm_handle *desc = NULL;
+ int ret = 0;
+
+ if (copy_from_user(&kern_op, user_op, sizeof(dom0_op_t)))
+ return -EFAULT;
+
+ if (kern_op.interface_version != DOM0_INTERFACE_VERSION)
+ return -EACCES;
+
+ op_desc = xencomm_create_inline(&kern_op);
+
+ switch (kern_op.cmd) {
+ default:
+ printk("%s: unknown dom0 cmd %d\n", __func__, kern_op.cmd);
+ return -ENOSYS;
+ }
+
+ if (ret) {
+ /* error mapping the nested pointer */
+ return ret;
+ }
+
+ ret = xencomm_arch_hypercall_dom0_op(op_desc);
+
+ /* FIXME: should we restore the handle? */
+ if (copy_to_user(user_op, &kern_op, sizeof(dom0_op_t)))
+ ret = -EFAULT;
+
+ if (desc)
+ xencomm_free(desc);
+ return ret;
+}
+
+static int
+xencomm_privcmd_sysctl(privcmd_hypercall_t *hypercall)
+{
+ xen_sysctl_t kern_op;
+ xen_sysctl_t __user *user_op;
+ struct xencomm_handle *op_desc;
+ struct xencomm_handle *desc = NULL;
+ struct xencomm_handle *desc1 = NULL;
+ int ret = 0;
+
+ user_op = (xen_sysctl_t __user *)hypercall->arg[0];
+
+ if (copy_from_user(&kern_op, user_op, sizeof(xen_sysctl_t)))
+ return -EFAULT;
+
+ if (kern_op.interface_version != XEN_SYSCTL_INTERFACE_VERSION)
+ return -EACCES;
+
+ op_desc = xencomm_create_inline(&kern_op);
+
+ switch (kern_op.cmd) {
+ case XEN_SYSCTL_readconsole:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.readconsole.buffer),
+ kern_op.u.readconsole.count,
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.readconsole.buffer,
+ (void *)desc);
+ break;
+ case XEN_SYSCTL_tbuf_op:
+ case XEN_SYSCTL_physinfo:
+ case XEN_SYSCTL_sched_id:
+ break;
+ case XEN_SYSCTL_perfc_op:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.perfc_op.desc),
+ kern_op.u.perfc_op.nr_counters *
+ sizeof(xen_sysctl_perfc_desc_t),
+ &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+ set_xen_guest_handle(kern_op.u.perfc_op.val,
+ (void *)desc);
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.perfc_op.val),
+ kern_op.u.perfc_op.nr_vals *
+ sizeof(xen_sysctl_perfc_desc_t),
+ &desc1, GFP_KERNEL);
+ if (ret)
+ xencomm_free(desc);
+ set_xen_guest_handle(kern_op.u.perfc_op.val,
+ (void *)desc1);
+ break;
+ case XEN_SYSCTL_getdomaininfolist:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.getdomaininfolist.buffer),
+ kern_op.u.getdomaininfolist.max_domains *
+ sizeof(xen_domctl_getdomaininfo_t),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer,
+ (void *)desc);
+ break;
+ default:
+ printk("%s: unknown sysctl cmd %d\n", __func__, kern_op.cmd);
+ return -ENOSYS;
+ }
+
+ if (ret) {
+ /* error mapping the nested pointer */
+ return ret;
+ }
+
+ ret = xencomm_arch_hypercall_sysctl(op_desc);
+
+ /* FIXME: should we restore the handle? */
+ if (copy_to_user(user_op, &kern_op, sizeof(xen_sysctl_t)))
+ ret = -EFAULT;
+
+ if (desc)
+ xencomm_free(desc);
+ if (desc1)
+ xencomm_free(desc1);
+ return ret;
+}
+
+static int
+xencomm_privcmd_domctl(privcmd_hypercall_t *hypercall)
+{
+ xen_domctl_t kern_op;
+ xen_domctl_t __user *user_op;
+ struct xencomm_handle *op_desc;
+ struct xencomm_handle *desc = NULL;
+ int ret = 0;
+
+ user_op = (xen_domctl_t __user *)hypercall->arg[0];
+
+ if (copy_from_user(&kern_op, user_op, sizeof(xen_domctl_t)))
+ return -EFAULT;
+
+ if (kern_op.interface_version != XEN_DOMCTL_INTERFACE_VERSION)
+ return -EACCES;
+
+ op_desc = xencomm_create_inline(&kern_op);
+
+ switch (kern_op.cmd) {
+ case XEN_DOMCTL_createdomain:
+ case XEN_DOMCTL_destroydomain:
+ case XEN_DOMCTL_pausedomain:
+ case XEN_DOMCTL_unpausedomain:
+ case XEN_DOMCTL_getdomaininfo:
+ break;
+ case XEN_DOMCTL_getmemlist:
+ {
+ unsigned long nr_pages = kern_op.u.getmemlist.max_pfns;
+
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.getmemlist.buffer),
+ nr_pages * sizeof(unsigned long),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.getmemlist.buffer,
+ (void *)desc);
+ break;
+ }
+ case XEN_DOMCTL_getpageframeinfo:
+ break;
+ case XEN_DOMCTL_getpageframeinfo2:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.getpageframeinfo2.array),
+ kern_op.u.getpageframeinfo2.num,
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.getpageframeinfo2.array,
+ (void *)desc);
+ break;
+ case XEN_DOMCTL_shadow_op:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap),
+ ROUND_DIV(kern_op.u.shadow_op.pages, 8),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap,
+ (void *)desc);
+ break;
+ case XEN_DOMCTL_max_mem:
+ break;
+ case XEN_DOMCTL_setvcpucontext:
+ case XEN_DOMCTL_getvcpucontext:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.vcpucontext.ctxt),
+ sizeof(vcpu_guest_context_t),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.vcpucontext.ctxt, (void *)desc);
+ break;
+ case XEN_DOMCTL_getvcpuinfo:
+ break;
+ case XEN_DOMCTL_setvcpuaffinity:
+ case XEN_DOMCTL_getvcpuaffinity:
+ ret = xencomm_create(
+ xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap),
+ ROUND_DIV(kern_op.u.vcpuaffinity.cpumap.nr_cpus, 8),
+ &desc, GFP_KERNEL);
+ set_xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap,
+ (void *)desc);
+ break;
+ case XEN_DOMCTL_max_vcpus:
+ case XEN_DOMCTL_scheduler_op:
+ case XEN_DOMCTL_setdomainhandle:
+ case XEN_DOMCTL_setdebugging:
+ case XEN_DOMCTL_irq_permission:
+ case XEN_DOMCTL_iomem_permission:
+ case XEN_DOMCTL_ioport_permission:
+ case XEN_DOMCTL_hypercall_init:
+ case XEN_DOMCTL_arch_setup:
+ case XEN_DOMCTL_settimeoffset:
+ break;
+ default:
+ printk("%s: unknown domctl cmd %d\n", __func__, kern_op.cmd);
+ return -ENOSYS;
+ }
+
+ if (ret) {
+ /* error mapping the nested pointer */
+ return ret;
+ }
+
+ ret = xencomm_arch_hypercall_domctl (op_desc);
+
+ /* FIXME: should we restore the handle? */
+ if (copy_to_user(user_op, &kern_op, sizeof(xen_domctl_t)))
+ ret = -EFAULT;
+
+ if (desc)
+ xencomm_free(desc);
+ return ret;
+}
+
+static int
+xencomm_privcmd_acm_op(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
+ void __user *arg = (void __user *)hypercall->arg[1];
+ struct xencomm_handle *op_desc;
+ struct xencomm_handle *desc = NULL;
+ int ret;
+
+ switch (cmd) {
+ case ACMOP_getssid:
+ {
+ struct acm_getssid kern_arg;
+
+ if (copy_from_user(&kern_arg, arg, sizeof (kern_arg)))
+ return -EFAULT;
+
+ op_desc = xencomm_create_inline(&kern_arg);
+
+ ret = xencomm_create(xen_guest_handle(kern_arg.ssidbuf),
+ kern_arg.ssidbuf_size, &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ set_xen_guest_handle(kern_arg.ssidbuf, (void *)desc);
+
+ ret = xencomm_arch_hypercall_acm_op(cmd, op_desc);
+
+ xencomm_free(desc);
+
+ if (copy_to_user(arg, &kern_arg, sizeof (kern_arg)))
+ return -EFAULT;
+
+ return ret;
+ }
+ default:
+ printk("%s: unknown acm_op cmd %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ return ret;
+}
+
+static int
+xencomm_privcmd_memory_op(privcmd_hypercall_t *hypercall)
+{
+ const unsigned long cmd = hypercall->arg[0];
+ int ret = 0;
+
+ switch (cmd) {
+ case XENMEM_increase_reservation:
+ case XENMEM_decrease_reservation:
+ case XENMEM_populate_physmap:
+ {
+ xen_memory_reservation_t kern_op;
+ xen_memory_reservation_t __user *user_op;
+ struct xencomm_handle *desc = NULL;
+ struct xencomm_handle *desc_op;
+
+ user_op = (xen_memory_reservation_t __user *)hypercall->arg[1];
+ if (copy_from_user(&kern_op, user_op,
+ sizeof(xen_memory_reservation_t)))
+ return -EFAULT;
+ desc_op = xencomm_create_inline(&kern_op);
+
+ if (xen_guest_handle(kern_op.extent_start)) {
+ void * addr;
+
+ addr = xen_guest_handle(kern_op.extent_start);
+ ret = xencomm_create
+ (addr,
+ kern_op.nr_extents *
+ sizeof(*xen_guest_handle
+ (kern_op.extent_start)),
+ &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+ set_xen_guest_handle(kern_op.extent_start,
+ (void *)desc);
+ }
+
+ ret = xencomm_arch_hypercall_memory_op(cmd, desc_op);
+
+ if (desc)
+ xencomm_free(desc);
+
+ if (ret != 0)
+ return ret;
+
+ if (copy_to_user(user_op, &kern_op,
+ sizeof(xen_memory_reservation_t)))
+ return -EFAULT;
+
+ return ret;
+ }
+ case XENMEM_translate_gpfn_list:
+ {
+ xen_translate_gpfn_list_t kern_op;
+ xen_translate_gpfn_list_t __user *user_op;
+ struct xencomm_handle *desc_gpfn = NULL;
+ struct xencomm_handle *desc_mfn = NULL;
+ struct xencomm_handle *desc_op;
+ void *addr;
+
+ user_op = (xen_translate_gpfn_list_t __user *)
+ hypercall->arg[1];
+ if (copy_from_user(&kern_op, user_op,
+ sizeof(xen_translate_gpfn_list_t)))
+ return -EFAULT;
+ desc_op = xencomm_create_inline(&kern_op);
+
+ if (kern_op.nr_gpfns) {
+ /* gpfn_list. */
+ addr = xen_guest_handle(kern_op.gpfn_list);
+
+ ret = xencomm_create(addr, kern_op.nr_gpfns *
+ sizeof(*xen_guest_handle
+ (kern_op.gpfn_list)),
+ &desc_gpfn, GFP_KERNEL);
+ if (ret)
+ return ret;
+ set_xen_guest_handle(kern_op.gpfn_list,
+ (void *)desc_gpfn);
+
+ /* mfn_list. */
+ addr = xen_guest_handle(kern_op.mfn_list);
+
+ ret = xencomm_create(addr, kern_op.nr_gpfns *
+ sizeof(*xen_guest_handle
+ (kern_op.mfn_list)),
+ &desc_mfn, GFP_KERNEL);
+ if (ret)
+ return ret;
+ set_xen_guest_handle(kern_op.mfn_list,
+ (void *)desc_mfn);
+ }
+
+ ret = xencomm_arch_hypercall_memory_op(cmd, desc_op);
+
+ if (desc_gpfn)
+ xencomm_free(desc_gpfn);
+
+ if (desc_mfn)
+ xencomm_free(desc_mfn);
+
+ if (ret != 0)
+ return ret;
+
+ return ret;
+ }
+ default:
+ printk("%s: unknown memory op %lu\n", __func__, cmd);
+ ret = -ENOSYS;
+ }
+ return ret;
+}
+
+static int
+xencomm_privcmd_xen_version(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
+ void __user *arg = (void __user *)hypercall->arg[1];
+ struct xencomm_handle *desc;
+ size_t argsize;
+ int rc;
+
+ switch (cmd) {
+ case XENVER_version:
+ /* do not actually pass an argument */
+ return xencomm_arch_hypercall_xen_version(cmd, 0);
+ case XENVER_extraversion:
+ argsize = sizeof(xen_extraversion_t);
+ break;
+ case XENVER_compile_info:
+ argsize = sizeof(xen_compile_info_t);
+ break;
+ case XENVER_capabilities:
+ argsize = sizeof(xen_capabilities_info_t);
+ break;
+ case XENVER_changeset:
+ argsize = sizeof(xen_changeset_info_t);
+ break;
+ case XENVER_platform_parameters:
+ argsize = sizeof(xen_platform_parameters_t);
+ break;
+ case XENVER_pagesize:
+ argsize = (arg == NULL) ? 0 : sizeof(void *);
+ break;
+ case XENVER_get_features:
+ argsize = (arg == NULL) ? 0 : sizeof(xen_feature_info_t);
+ break;
+
+ default:
+ printk("%s: unknown version op %d\n", __func__, cmd);
+ return -ENOSYS;
+ }
+
+ rc = xencomm_create(arg, argsize, &desc, GFP_KERNEL);
+ if (rc)
+ return rc;
+
+ rc = xencomm_arch_hypercall_xen_version(cmd, desc);
+
+ xencomm_free(desc);
+
+ return rc;
+}
+
+static int
+xencomm_privcmd_event_channel_op(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
+ struct xencomm_handle *desc;
+ unsigned int argsize;
+ int ret;
+
+ switch (cmd) {
+ case EVTCHNOP_alloc_unbound:
+ argsize = sizeof(evtchn_alloc_unbound_t);
+ break;
+
+ case EVTCHNOP_status:
+ argsize = sizeof(evtchn_status_t);
+ break;
+
+ default:
+ printk("%s: unknown EVTCHNOP %d\n", __func__, cmd);
+ return -EINVAL;
+ }
+
+ ret = xencomm_create((void *)hypercall->arg[1], argsize,
+ &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ ret = xencomm_arch_hypercall_event_channel_op(cmd, desc);
+
+ xencomm_free(desc);
+ return ret;
+}
+
+static int
+xencomm_privcmd_hvm_op(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
+ struct xencomm_handle *desc;
+ unsigned int argsize;
+ int ret;
+
+ switch (cmd) {
+ case HVMOP_get_param:
+ case HVMOP_set_param:
+ argsize = sizeof(xen_hvm_param_t);
+ break;
+ default:
+ printk("%s: unknown HVMOP %d\n", __func__, cmd);
+ return -EINVAL;
+ }
+
+ ret = xencomm_create((void *)hypercall->arg[1], argsize,
+ &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ ret = xencomm_arch_hypercall_hvm_op(cmd, desc);
+
+ xencomm_free(desc);
+ return ret;
+}
+
+static int
+xencomm_privcmd_sched_op(privcmd_hypercall_t *hypercall)
+{
+ int cmd = hypercall->arg[0];
+ struct xencomm_handle *desc;
+ unsigned int argsize;
+ int ret;
+
+ switch (cmd) {
+ case SCHEDOP_remote_shutdown:
+ argsize = sizeof(sched_remote_shutdown_t);
+ break;
+ default:
+ printk("%s: unknown SCHEDOP %d\n", __func__, cmd);
+ return -EINVAL;
+ }
+
+ ret = xencomm_create((void *)hypercall->arg[1], argsize,
+ &desc, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ ret = xencomm_arch_hypercall_sched_op(cmd, desc);
+
+ xencomm_free(desc);
+ return ret;
+}
+
+int
+privcmd_hypercall(privcmd_hypercall_t *hypercall)
+{
+ switch (hypercall->op) {
+ case __HYPERVISOR_dom0_op:
+ return xencomm_privcmd_dom0_op(hypercall);
+ case __HYPERVISOR_domctl:
+ return xencomm_privcmd_domctl(hypercall);
+ case __HYPERVISOR_sysctl:
+ return xencomm_privcmd_sysctl(hypercall);
+ case __HYPERVISOR_acm_op:
+ return xencomm_privcmd_acm_op(hypercall);
+ case __HYPERVISOR_xen_version:
+ return xencomm_privcmd_xen_version(hypercall);
+ case __HYPERVISOR_memory_op:
+ return xencomm_privcmd_memory_op(hypercall);
+ case __HYPERVISOR_event_channel_op:
+ return xencomm_privcmd_event_channel_op(hypercall);
+ case __HYPERVISOR_hvm_op:
+ return xencomm_privcmd_hvm_op(hypercall);
+ case __HYPERVISOR_sched_op:
+ return xencomm_privcmd_sched_op(hypercall);
+ default:
+ printk("%s: unknown hcall (%ld)\n", __func__, hypercall->op);
+ return -ENOSYS;
+ }
+}
+
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c b/linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c
new file mode 100644
index 0000000000..3767e893fc
--- /dev/null
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xencomm.c
@@ -0,0 +1,258 @@
+/*
+ * 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>
+#include <asm/xen/xencomm.h>
+
+static int xencomm_debug = 0;
+
+static unsigned long kernel_start_pa;
+
+void
+xencomm_init (void)
+{
+ kernel_start_pa = KERNEL_START - ia64_tpa(KERNEL_START);
+}
+
+/* Translate virtual address to physical address. */
+unsigned long
+xencomm_vaddr_to_paddr(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
+}
+
+static int
+xencomm_init_desc(struct xencomm_desc *desc, void *buffer, unsigned long bytes)
+{
+ unsigned long recorded = 0;
+ int i = 0;
+
+ BUG_ON((buffer == NULL) && (bytes > 0));
+
+ /* record the physical pages used */
+ if (buffer == NULL)
+ desc->nr_addrs = 0;
+
+ while ((recorded < bytes) && (i < desc->nr_addrs)) {
+ unsigned long vaddr = (unsigned long)buffer + recorded;
+ unsigned long paddr;
+ int offset;
+ int chunksz;
+
+ offset = vaddr % PAGE_SIZE; /* handle partial pages */
+ chunksz = min(PAGE_SIZE - offset, bytes - recorded);
+
+ paddr = xencomm_vaddr_to_paddr(vaddr);
+ if (paddr == ~0UL) {
+ printk("%s: couldn't translate vaddr %lx\n",
+ __func__, vaddr);
+ return -EINVAL;
+ }
+
+ desc->address[i++] = paddr;
+ recorded += chunksz;
+ }
+
+ if (recorded < bytes) {
+ printk("%s: could only translate %ld of %ld bytes\n",
+ __func__, recorded, bytes);
+ return -ENOSPC;
+ }
+
+ /* mark remaining addresses invalid (just for safety) */
+ while (i < desc->nr_addrs)
+ desc->address[i++] = XENCOMM_INVALID;
+
+ desc->magic = XENCOMM_MAGIC;
+
+ return 0;
+}
+
+static struct xencomm_desc *
+xencomm_alloc(gfp_t gfp_mask)
+{
+ struct xencomm_desc *desc;
+
+ desc = (struct xencomm_desc *)__get_free_page(gfp_mask);
+ if (desc == NULL)
+ panic("%s: page allocation failed\n", __func__);
+
+ desc->nr_addrs = (PAGE_SIZE - sizeof(struct xencomm_desc)) /
+ sizeof(*desc->address);
+
+ return desc;
+}
+
+void
+xencomm_free(struct xencomm_handle *desc)
+{
+ if (desc)
+ free_page((unsigned long)__va(desc));
+}
+
+int
+xencomm_create(void *buffer, unsigned long bytes,
+ struct xencomm_handle **ret, gfp_t gfp_mask)
+{
+ struct xencomm_desc *desc;
+ struct xencomm_handle *handle;
+ int rc;
+
+ if (xencomm_debug)
+ printk("%s: %p[%ld]\n", __func__, buffer, bytes);
+
+ if (buffer == NULL || bytes == 0) {
+ *ret = (struct xencomm_handle *)NULL;
+ return 0;
+ }
+
+ desc = xencomm_alloc(gfp_mask);
+ if (!desc) {
+ printk("%s failure\n", "xencomm_alloc");
+ return -ENOMEM;
+ }
+ handle = (struct xencomm_handle *)__pa(desc);
+
+ rc = xencomm_init_desc(desc, buffer, bytes);
+ if (rc) {
+ printk("%s failure: %d\n", "xencomm_init_desc", rc);
+ xencomm_free(handle);
+ return rc;
+ }
+
+ *ret = handle;
+ return 0;
+}
+
+/* "mini" routines, for stack-based communications: */
+
+static void *
+xencomm_alloc_mini(struct xencomm_mini *area, int *nbr_area)
+{
+ unsigned long base;
+ unsigned int pageoffset;
+
+ while (*nbr_area >= 0) {
+ /* Allocate an area. */
+ (*nbr_area)--;
+
+ base = (unsigned long)(area + *nbr_area);
+ pageoffset = base % PAGE_SIZE;
+
+ /* If the area does not cross a page, use it. */
+ if ((PAGE_SIZE - pageoffset) >= sizeof(struct xencomm_mini))
+ return &area[*nbr_area];
+ }
+ /* No more area. */
+ return NULL;
+}
+
+int
+xencomm_create_mini(struct xencomm_mini *area, int *nbr_area,
+ void *buffer, unsigned long bytes,
+ struct xencomm_handle **ret)
+{
+ struct xencomm_desc *desc;
+ int rc;
+ unsigned long res;
+
+ desc = xencomm_alloc_mini(area, nbr_area);
+ if (!desc)
+ return -ENOMEM;
+ desc->nr_addrs = XENCOMM_MINI_ADDRS;
+
+ rc = xencomm_init_desc(desc, buffer, bytes);
+ if (rc)
+ return rc;
+
+ res = xencomm_vaddr_to_paddr((unsigned long)desc);
+ if (res == ~0UL)
+ return -EINVAL;
+
+ *ret = (struct xencomm_handle*)res;
+ return 0;
+}
diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S b/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S
index 918622918e..e761278670 100644
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xensetup.S
@@ -23,12 +23,11 @@ GLOBAL_ENTRY(early_xen_setup)
mov cr.iva=r10
-#if XSI_BASE != 0xf100000000000000UL
- /* Backward compatibility. */
-(isBP) mov r2=0x600
+ /* 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;;
-#endif
br.ret.sptk.many rp
;;
@@ -38,18 +37,18 @@ END(early_xen_setup)
/* Stub for suspend.
Just force the stacked registers to be written in memory. */
-GLOBAL_ENTRY(HYPERVISOR_suspend)
+GLOBAL_ENTRY(xencomm_arch_hypercall_suspend)
+ mov r15=r32
+ ;;
alloc r20=ar.pfs,0,0,0,0
- mov r14=2
- mov r15=r12
- ;;
+ mov r2=__HYPERVISOR_sched_op
+ ;;
/* We don't want to deal with RSE. */
flushrs
- mov r2=__HYPERVISOR_sched_op
- st4 [r12]=r14
+ mov r14=2 // SCHEDOP_shutdown
;;
break 0x1000
;;
mov ar.pfs=r20
br.ret.sptk.many b0
-END(HYPERVISOR_suspend)
+END(xencomm_arch_hypercall_suspend)
diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
index ba67bec83e..a65b8744c2 100644
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
@@ -87,18 +87,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
: "r8", "r10", "memory" );
}
#elif defined (__ia64__)
- __asm__ __volatile__ (
- ";; mov r14=%2; mov r15=%3; "
- "mov r16=%4; mov r17=%5; mov r18=%6;"
- "mov r2=%1; break 0x1000;; mov %0=r8 ;;"
- : "=r" (ret)
- : "r" (hypercall.op),
- "r" (hypercall.arg[0]),
- "r" (hypercall.arg[1]),
- "r" (hypercall.arg[2]),
- "r" (hypercall.arg[3]),
- "r" (hypercall.arg[4])
- : "r14","r15","r16","r17","r18","r2","r8","memory");
+ ret = privcmd_hypercall(&hypercall);
#endif
}
break;
diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
index 8375336941..43f88b1930 100644
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
@@ -33,12 +33,13 @@
#ifndef __HYPERCALL_H__
#define __HYPERCALL_H__
-#include <linux/string.h> /* memcpy() */
-
#ifndef __HYPERVISOR_H__
# error "please don't include this file directly"
#endif
+#include <asm/xen/xcom_hcall.h>
+struct xencomm_handle;
+
/*
* Assembler stubs for hyper-calls.
*/
@@ -157,157 +158,117 @@
(type)__res; \
})
-static inline int
-HYPERVISOR_sched_op_compat(
- int cmd, unsigned long arg)
-{
- return _hypercall2(int, sched_op_compat, cmd, arg);
-}
static inline int
-HYPERVISOR_sched_op(
- int cmd, void *arg)
+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)
+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);
+ 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
-HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
+xencomm_arch_hypercall_dom0_op(struct xencomm_handle *op)
{
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- return _hypercall1(int, dom0_op, dom0_op);
+ return _hypercall1(int, dom0_op, op);
}
static inline int
-HYPERVISOR_multicall(
- void *call_list, int nr_calls)
+xencomm_arch_hypercall_sysctl(struct xencomm_handle *op)
{
- return _hypercall2(int, multicall, call_list, nr_calls);
+ return _hypercall1(int, sysctl, op);
}
-//XXX xen/ia64 copy_from_guest() is broken.
-// This is a temporal work around until it is fixed.
static inline int
-____HYPERVISOR_memory_op(
- unsigned int cmd, void *arg)
+xencomm_arch_hypercall_domctl(struct xencomm_handle *op)
{
- return _hypercall2(int, memory_op, cmd, arg);
+ return _hypercall1(int, domctl, op);
}
-#include <xen/interface/memory.h>
-#ifdef CONFIG_VMX_GUEST
-# define ia64_xenmem_reservation_op(op, xmr) (0)
-#else
-int ia64_xenmem_reservation_op(unsigned long op,
- struct xen_memory_reservation* reservation__);
-#endif
static inline int
-HYPERVISOR_memory_op(
- unsigned int cmd, void *arg)
+xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list,
+ int nr_calls)
{
- switch (cmd) {
- case XENMEM_increase_reservation:
- case XENMEM_decrease_reservation:
- case XENMEM_populate_physmap:
- return ia64_xenmem_reservation_op(cmd,
- (struct xen_memory_reservation*)arg);
- default:
- return ____HYPERVISOR_memory_op(cmd, arg);
- }
- /* NOTREACHED */
+ return _hypercall2(int, multicall, call_list, nr_calls);
}
static inline int
-HYPERVISOR_event_channel_op(
- int cmd, void *arg)
+xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg)
{
- int rc = _hypercall2(int, event_channel_op, cmd, arg);
- if (unlikely(rc == -ENOSYS)) {
- struct evtchn_op op;
- op.cmd = cmd;
- memcpy(&op.u, arg, sizeof(op.u));
- rc = _hypercall1(int, event_channel_op_compat, &op);
- }
- return rc;
+ return _hypercall2(int, memory_op, cmd, arg);
}
static inline int
-HYPERVISOR_acm_op(
- unsigned int cmd, void *arg)
+xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg)
{
- return _hypercall2(int, acm_op, cmd, arg);
+ return _hypercall2(int, event_channel_op, cmd, arg);
}
static inline int
-HYPERVISOR_xen_version(
- int cmd, void *arg)
+xencomm_arch_hypercall_acm_op(unsigned int cmd, struct xencomm_handle *arg)
{
- return _hypercall2(int, xen_version, cmd, arg);
+ return _hypercall2(int, acm_op, cmd, arg);
}
static inline int
-HYPERVISOR_console_io(
- int cmd, int count, char *str)
+xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg)
{
- return _hypercall3(int, console_io, cmd, count, str);
+ return _hypercall2(int, xen_version, cmd, arg);
}
static inline int
-HYPERVISOR_physdev_op(
- int cmd, void *arg)
+xencomm_arch_hypercall_console_io(int cmd, int count,
+ struct xencomm_handle *str)
{
- int rc = _hypercall2(int, physdev_op, cmd, arg);
- if (unlikely(rc == -ENOSYS)) {
- struct physdev_op op;
- op.cmd = cmd;
- memcpy(&op.u, arg, sizeof(op.u));
- rc = _hypercall1(int, physdev_op_compat, &op);
- }
- return rc;
+ return _hypercall3(int, console_io, cmd, count, str);
}
-//XXX __HYPERVISOR_grant_table_op is used for this hypercall constant.
static inline int
-____HYPERVISOR_grant_table_op(
- unsigned int cmd, void *uop, unsigned int count,
- unsigned long pa1, unsigned long pa2)
+xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg)
{
- return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2);
+ 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
-HYPERVISOR_vcpu_op(
- int cmd, int vcpuid, void *extra_args)
+xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg)
{
- return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
+ return _hypercall2(int, callback_op, cmd, arg);
}
-extern int HYPERVISOR_suspend(unsigned long srec);
-
static inline unsigned long
-HYPERVISOR_hvm_op(
- int cmd, void *arg)
+xencomm_arch_hypercall_hvm_op(int cmd, void *arg)
{
return _hypercall2(unsigned long, hvm_op, cmd, arg);
}
static inline int
-HYPERVISOR_callback_op(
- int cmd, void *arg)
+HYPERVISOR_physdev_op(int cmd, void *arg)
{
- return _hypercall2(int, callback_op, cmd, 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);
+ }
}
extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
@@ -417,7 +378,42 @@ HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn,
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);
+}
+#endif
+
// for balloon driver
#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0)
+/* Use xencomm to do hypercalls. */
+#ifdef MODULE
+#define HYPERVISOR_sched_op xencomm_mini_hypercall_sched_op
+#define HYPERVISOR_event_channel_op xencomm_mini_hypercall_event_channel_op
+#define HYPERVISOR_callback_op xencomm_mini_hypercall_callback_op
+#define HYPERVISOR_multicall xencomm_mini_hypercall_multicall
+#define HYPERVISOR_xen_version xencomm_mini_hypercall_xen_version
+#define HYPERVISOR_console_io xencomm_mini_hypercall_console_io
+#define HYPERVISOR_hvm_op xencomm_mini_hypercall_hvm_op
+#define HYPERVISOR_memory_op xencomm_mini_hypercall_memory_op
+#else
+#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
+#endif
+
+#define HYPERVISOR_suspend xencomm_hypercall_suspend
+
#endif /* __HYPERCALL_H__ */
diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
index acdf51203a..43db0a2367 100644
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
@@ -75,9 +75,6 @@ HYPERVISOR_yield(
{
int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
- if (rc == -ENOSYS)
- rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
-
return rc;
}
@@ -87,9 +84,6 @@ HYPERVISOR_block(
{
int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
- if (rc == -ENOSYS)
- rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
-
return rc;
}
@@ -103,9 +97,6 @@ HYPERVISOR_shutdown(
int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
- if (rc == -ENOSYS)
- rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
-
return rc;
}
@@ -122,8 +113,6 @@ HYPERVISOR_poll(
set_xen_guest_handle(sched_poll.ports, ports);
rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
- if (rc == -ENOSYS)
- rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
return rc;
}
diff --git a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h
index 55c6f94d10..7a26b2c6cc 100644
--- a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h
+++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h
@@ -10,11 +10,26 @@
#define INVALID_P2M_ENTRY (~0UL)
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
+extern int p2m_initialized;
+extern unsigned long p2m_min_low_pfn;
+extern unsigned long p2m_max_low_pfn;
+extern unsigned long p2m_convert_min_pfn;
+extern unsigned long p2m_convert_max_pfn;
+extern volatile const pte_t* p2m_pte;
+unsigned long p2m_phystomach(unsigned long gpfn);
+#else
+#define p2m_initialized (0)
+#define p2m_phystomach(gpfn) INVALID_MFN
+#endif
+
/* XXX xen page size != page size */
static inline unsigned long
pfn_to_mfn_for_dma(unsigned long pfn)
{
unsigned long mfn;
+ if (p2m_initialized)
+ return p2m_phystomach(pfn);
mfn = HYPERVISOR_phystomach(pfn);
BUG_ON(mfn == 0); // XXX
BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX
diff --git a/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h b/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h
index 073b3a2a77..6f3c20a8ed 100644
--- a/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h
+++ b/linux-2.6-xen-sparse/include/asm-ia64/xen/privop.h
@@ -14,12 +14,9 @@
#define IA64_PARAVIRTUALIZED
-#if 0
-#undef XSI_BASE
/* At 1 MB, before per-cpu space but still addressable using addl instead
of movl. */
#define XSI_BASE 0xfffffffffff00000
-#endif
/* Address of mapped regs. */
#define XMAPPEDREGS_BASE (XSI_BASE + XSI_SIZE)
diff --git a/linux-2.6-xen-sparse/include/asm-ia64/xen/xcom_hcall.h b/linux-2.6-xen-sparse/include/asm-ia64/xen/xcom_hcall.h
new file mode 100644
index 0000000000..3c073a71cd
--- /dev/null
+++ b/linux-2.6-xen-sparse/include/asm-ia64/xen/xcom_hcall.h
@@ -0,0 +1,76 @@
+/*
+ * 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 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);
+
+/* Using mini xencomm. */
+extern int xencomm_mini_hypercall_console_io(int cmd, int count, char *str);
+
+extern int xencomm_mini_hypercall_event_channel_op(int cmd, void *op);
+
+extern int xencomm_mini_hypercall_xen_version(int cmd, void *arg);
+
+extern int xencomm_mini_hypercall_physdev_op(int cmd, void *op);
+
+extern int xencomm_mini_hypercall_grant_table_op(unsigned int cmd, void *op,
+ unsigned int count);
+
+extern int xencomm_mini_hypercall_sched_op(int cmd, void *arg);
+
+extern int xencomm_mini_hypercall_multicall(void *call_list, int nr_calls);
+
+extern int xencomm_mini_hypercall_callback_op(int cmd, void *arg);
+
+extern int xencomm_mini_hypercall_memory_op(unsigned int cmd, void *arg);
+
+extern unsigned long xencomm_mini_hypercall_hvm_op(int cmd, void *arg);
+
+/* For privcmd. Locally declare argument type to avoid include storm.
+ Type coherency will be checked within privcmd.c */
+struct privcmd_hypercall;
+extern int privcmd_hypercall(struct privcmd_hypercall *hypercall);
+
+#endif /* _LINUX_XENCOMM_HCALL_H_ */
diff --git a/linux-2.6-xen-sparse/include/asm-ia64/xen/xencomm.h b/linux-2.6-xen-sparse/include/asm-ia64/xen/xencomm.h
new file mode 100644
index 0000000000..eae11369f1
--- /dev/null
+++ b/linux-2.6-xen-sparse/include/asm-ia64/xen/xencomm.h
@@ -0,0 +1,60 @@
+/*
+ * 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 _LINUX_XENCOMM_H_
+#define _LINUX_XENCOMM_H_
+
+#include <xen/interface/xencomm.h>
+
+#define XENCOMM_MINI_ADDRS 3
+struct xencomm_mini {
+ struct xencomm_desc _desc;
+ uint64_t address[XENCOMM_MINI_ADDRS];
+};
+
+/* Must be called before any hypercall. */
+extern void xencomm_init (void);
+
+/* To avoid additionnal virt to phys conversion, an opaque structure is
+ presented. */
+struct xencomm_handle;
+
+extern int xencomm_create(void *buffer, unsigned long bytes,
+ struct xencomm_handle **desc, gfp_t type);
+extern void xencomm_free(struct xencomm_handle *desc);
+
+extern int xencomm_create_mini(struct xencomm_mini *area, int *nbr_area,
+ void *buffer, unsigned long bytes,
+ struct xencomm_handle **ret);
+
+/* Translate virtual address to physical address. */
+extern unsigned long xencomm_vaddr_to_paddr(unsigned long vaddr);
+
+/* Inline version. To be used only on linear space (kernel space). */
+static inline struct xencomm_handle *
+xencomm_create_inline(void *buffer)
+{
+ unsigned long paddr;
+
+ paddr = xencomm_vaddr_to_paddr((unsigned long)buffer);
+ return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
+}
+
+#define xen_guest_handle(hnd) ((hnd).p)
+
+#endif /* _LINUX_XENCOMM_H_ */
diff --git a/linux-2.6-xen-sparse/lib/Makefile b/linux-2.6-xen-sparse/lib/Makefile
index 2657bb5d10..1f96de0517 100644
--- a/linux-2.6-xen-sparse/lib/Makefile
+++ b/linux-2.6-xen-sparse/lib/Makefile
@@ -45,9 +45,7 @@ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
obj-$(CONFIG_SWIOTLB) += swiotlb.o
-ifneq ($(CONFIG_XEN_IA64_DOM0_NON_VP),y)
swiotlb-$(CONFIG_XEN) := ../arch/i386/kernel/swiotlb.o
-endif
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/tools/libxc/ia64/xc_ia64_linux_restore.c b/tools/libxc/ia64/xc_ia64_linux_restore.c
index df6cf9dab6..e6aed35ead 100644
--- a/tools/libxc/ia64/xc_ia64_linux_restore.c
+++ b/tools/libxc/ia64/xc_ia64_linux_restore.c
@@ -225,6 +225,9 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
goto out;
}
+ fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt.user_regs.cr_iip,
+ ctxt.user_regs.b0);
+
/* First to initialize. */
domctl.cmd = XEN_DOMCTL_setvcpucontext;
domctl.domain = (domid_t)dom;
diff --git a/tools/libxc/ia64/xc_ia64_linux_save.c b/tools/libxc/ia64/xc_ia64_linux_save.c
index 68b7749954..42ec21c802 100644
--- a/tools/libxc/ia64/xc_ia64_linux_save.c
+++ b/tools/libxc/ia64/xc_ia64_linux_save.c
@@ -458,6 +458,9 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
+ fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt.user_regs.cr_iip,
+ ctxt.user_regs.b0);
+
mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE, ctxt.privregs_pfn);
if (mem == NULL) {
diff --git a/unmodified_drivers/linux-2.6/mkbuildtree b/unmodified_drivers/linux-2.6/mkbuildtree
index be6b1a6d94..ce0a142447 100644
--- a/unmodified_drivers/linux-2.6/mkbuildtree
+++ b/unmodified_drivers/linux-2.6/mkbuildtree
@@ -27,6 +27,7 @@ mkdir -p include
mkdir -p include/xen
mkdir -p include/public
mkdir -p include/asm
+mkdir -p include/asm/xen
lndir -silent ${XL}/include/xen include/xen
ln -sf ${XEN}/include/public include/xen/interface
@@ -54,6 +55,10 @@ i[34567]86)
ln -sf ${XL}/include/asm-ia64/hypercall.h include/asm
ln -sf ${XL}/include/asm-ia64/synch_bitops.h include/asm
ln -sf ${XL}/include/asm-ia64/maddr.h include/asm
+ ln -sf ${XL}/include/asm-ia64/xen/xcom_hcall.h include/asm/xen
+ ln -sf ${XL}/include/asm-ia64/xen/xencomm.h include/asm/xen
+ ln -sf ${XL}/arch/ia64/xen/xcom_mini.c platform-pci
+ ln -sf ${XL}/arch/ia64/xen/xencomm.c platform-pci
;;
*)
echo unknown architecture $uname
diff --git a/unmodified_drivers/linux-2.6/platform-pci/Kbuild b/unmodified_drivers/linux-2.6/platform-pci/Kbuild
index a4c1961a8a..dda3d0e7cf 100644
--- a/unmodified_drivers/linux-2.6/platform-pci/Kbuild
+++ b/unmodified_drivers/linux-2.6/platform-pci/Kbuild
@@ -5,3 +5,8 @@ obj-m := xen-platform-pci.o
EXTRA_CFLAGS += -I$(M)/platform-pci
xen-platform-pci-objs := evtchn.o platform-pci.o gnttab.o xen_support.o features.o
+
+# Can we do better ?
+ifeq ($(ARCH),ia64)
+ xen-platform-pci-objs += xcom_mini.o xencomm.o
+endif
diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
index 36ad585fbf..cb9e8dd7e5 100644
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
@@ -35,6 +35,9 @@
#include <asm/hypervisor.h>
#include <xen/interface/memory.h>
#include <xen/features.h>
+#ifdef __ia64__
+#include <asm/xen/xencomm.h>
+#endif
#include "platform-pci.h"
@@ -59,6 +62,10 @@ static int __init init_xen_info(void)
struct xen_add_to_physmap xatp;
extern void *shared_info_area;
+#ifdef __ia64__
+ xencomm_init();
+#endif
+
setup_xen_features();
shared_info_frame = alloc_xen_mmio(PAGE_SIZE) >> PAGE_SHIFT;
diff --git a/xen/arch/ia64/Rules.mk b/xen/arch/ia64/Rules.mk
index 944d8d018e..8f69704d7d 100644
--- a/xen/arch/ia64/Rules.mk
+++ b/xen/arch/ia64/Rules.mk
@@ -5,6 +5,11 @@ HAS_ACPI := y
HAS_VGA := y
VALIDATE_VT ?= n
no_warns ?= n
+xen_ia64_expose_p2m ?= y
+xen_ia64_pervcpu_vhpt ?= y
+xen_ia64_tlb_track ?= y
+xen_ia64_tlb_track_cnt ?= n
+xen_ia64_tlbflush_clock ?= y
ifneq ($(COMPILE_ARCH),$(TARGET_ARCH))
CROSS_COMPILE ?= /usr/local/sp_env/v2.2.5/i686/bin/ia64-unknown-linux-
@@ -34,6 +39,21 @@ CFLAGS += -g
ifeq ($(VALIDATE_VT),y)
CFLAGS += -DVALIDATE_VT
endif
+ifeq ($(xen_ia64_expose_p2m),y)
+CFLAGS += -DCONFIG_XEN_IA64_EXPOSE_P2M
+endif
+ifeq ($(xen_ia64_pervcpu_vhpt),y)
+CFLAGS += -DCONFIG_XEN_IA64_PERVCPU_VHPT
+endif
+ifeq ($(xen_ia64_tlb_track),y)
+CFLAGS += -DCONFIG_XEN_IA64_TLB_TRACK
+endif
+ifeq ($(xen_ia64_tlb_track_cnt),y)
+CFLAGS += -DCONFIG_TLB_TRACK_CNT
+endif
+ifeq ($(xen_ia64_tlbflush_clock),y)
+CFLAGS += -DCONFIG_XEN_IA64_TLBFLUSH_CLOCK
+endif
ifeq ($(no_warns),y)
CFLAGS += -Wa,--fatal-warnings -Werror -Wno-uninitialized
endif
diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c
index 67b5725c56..32a7d076aa 100644
--- a/xen/arch/ia64/asm-offsets.c
+++ b/xen/arch/ia64/asm-offsets.c
@@ -37,6 +37,8 @@ void foo(void)
DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET, offsetof (struct ia64_mca_cpu, init_stack));
BLANK();
+ DEFINE(VCPU_VTM_OFFSET_OFS, offsetof(struct vcpu, arch.arch_vmx.vtm.vtm_offset));
+ DEFINE(VCPU_VRR0_OFS, offsetof(struct vcpu, arch.arch_vmx.vrr[0]));
#ifdef VTI_DEBUG
DEFINE(IVT_CUR_OFS, offsetof(struct vcpu, arch.arch_vmx.ivt_current));
DEFINE(IVT_DBG_OFS, offsetof(struct vcpu, arch.arch_vmx.ivt_debug));
@@ -139,6 +141,7 @@ void foo(void)
DEFINE(SWITCH_MPTA_OFFSET,offsetof(struct vcpu ,arch.arch_vmx.mpta));
DEFINE(IA64_PT_REGS_R16_SLOT, (((offsetof(struct pt_regs, r16)-sizeof(struct pt_regs))>>3)&0x3f));
DEFINE(IA64_VCPU_FLAGS_OFFSET,offsetof(struct vcpu ,arch.arch_vmx.flags));
+ DEFINE(IA64_VCPU_MODE_FLAGS_OFFSET,offsetof(struct vcpu, arch.mode_flags));
BLANK();
diff --git a/xen/arch/ia64/linux-xen/entry.S b/xen/arch/ia64/linux-xen/entry.S
index d80be440a3..2c73fc5d2b 100644
--- a/xen/arch/ia64/linux-xen/entry.S
+++ b/xen/arch/ia64/linux-xen/entry.S
@@ -262,13 +262,15 @@ GLOBAL_ENTRY(ia64_switch_to)
#endif
rsm psr.ic // interrupts (psr.i) are already disabled here
movl r25=PAGE_KERNEL
+ movl r26 = IA64_GRANULE_SHIFT << 2
;;
srlz.d
or r23=r25,r20 // construct PA | page properties
- mov r25=IA64_GRANULE_SHIFT<<2
+ ptr.d in0, r26 // to purge dtr[IA64_TR_VHPT]
;;
- mov cr.itir=r25
+ mov cr.itir=r26
mov cr.ifa=in0 // VA of next task...
+ srlz.d
;;
mov r25=IA64_TR_CURRENT_STACK
#ifdef XEN
diff --git a/xen/arch/ia64/linux-xen/mca.c b/xen/arch/ia64/linux-xen/mca.c
index 1e4a86061b..30803daced 100644
--- a/xen/arch/ia64/linux-xen/mca.c
+++ b/xen/arch/ia64/linux-xen/mca.c
@@ -80,6 +80,7 @@
#ifdef XEN
#include <xen/symbols.h>
#include <xen/mm.h>
+#include <xen/console.h>
#endif
#if defined(IA64_MCA_DEBUG_INFO)
@@ -1240,6 +1241,7 @@ ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
*/
ms = (pal_min_state_area_t *)(ia64_sal_to_os_handoff_state.pal_min_state | (6ul<<61));
#else
+ console_start_sync();
/* Xen virtual address in region 7. */
ms = __va((pal_min_state_area_t *)(ia64_sal_to_os_handoff_state[cpu].pal_min_state));
#endif
diff --git a/xen/arch/ia64/linux-xen/sal.c b/xen/arch/ia64/linux-xen/sal.c
index ad81a29ad8..59cc613bbb 100644
--- a/xen/arch/ia64/linux-xen/sal.c
+++ b/xen/arch/ia64/linux-xen/sal.c
@@ -16,8 +16,10 @@
#ifdef XEN
#include <linux/smp.h>
+#include <asm/hw_irq.h>
#include <xen/lib.h>
#endif
+#include <asm/delay.h>
#include <asm/page.h>
#include <asm/sal.h>
#include <asm/pal.h>
@@ -218,6 +220,77 @@ chk_nointroute_opt(void)
static void __init sal_desc_ap_wakeup(void *p) { }
#endif
+/*
+ * HP rx5670 firmware polls for interrupts during SAL_CACHE_FLUSH by reading
+ * cr.ivr, but it never writes cr.eoi. This leaves any interrupt marked as
+ * "in-service" and masks other interrupts of equal or lower priority.
+ *
+ * HP internal defect reports: F1859, F2775, F3031.
+ */
+static int sal_cache_flush_drops_interrupts;
+
+static void __init
+check_sal_cache_flush (void)
+{
+ unsigned long flags, itv;
+ int cpu;
+ u64 vector;
+
+ cpu = get_cpu();
+ local_irq_save(flags);
+
+ /*
+ * Schedule a timer interrupt, wait until it's reported, and see if
+ * SAL_CACHE_FLUSH drops it.
+ */
+ itv = ia64_get_itv();
+ BUG_ON((itv & (1 << 16)) == 0);
+
+ ia64_set_itv(IA64_TIMER_VECTOR);
+ ia64_set_itm(ia64_get_itc() + 1000);
+
+ while (!ia64_get_irr(IA64_TIMER_VECTOR))
+ cpu_relax();
+
+ ia64_sal_cache_flush(3);
+
+ if (ia64_get_irr(IA64_TIMER_VECTOR)) {
+ vector = ia64_get_ivr();
+ ia64_eoi();
+ } else {
+ sal_cache_flush_drops_interrupts = 1;
+ printk(KERN_ERR "SAL: SAL_CACHE_FLUSH drops interrupts; "
+ "PAL_CACHE_FLUSH will be used instead\n");
+ ia64_eoi();
+ }
+
+ ia64_set_itv(itv);
+ local_irq_restore(flags);
+ put_cpu();
+}
+
+s64
+ia64_sal_cache_flush (u64 cache_type)
+{
+ struct ia64_sal_retval isrv;
+
+ if (sal_cache_flush_drops_interrupts) {
+ unsigned long flags;
+ u64 progress;
+ s64 rc;
+
+ progress = 0;
+ local_irq_save(flags);
+ rc = ia64_pal_cache_flush(cache_type,
+ PAL_CACHE_FLUSH_INVALIDATE, &progress, NULL);
+ local_irq_restore(flags);
+ return rc;
+ }
+
+ SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
+ return isrv.status;
+}
+
void __init
ia64_sal_init (struct ia64_sal_systab *systab)
{
@@ -271,6 +344,8 @@ ia64_sal_init (struct ia64_sal_systab *systab)
}
p += SAL_DESC_SIZE(*p);
}
+
+ check_sal_cache_flush();
}
int
diff --git a/xen/arch/ia64/linux-xen/tlb.c b/xen/arch/ia64/linux-xen/tlb.c
index 9859923b77..2a6bffffb3 100644
--- a/xen/arch/ia64/linux-xen/tlb.c
+++ b/xen/arch/ia64/linux-xen/tlb.c
@@ -111,7 +111,10 @@ void
local_flush_tlb_all (void)
{
unsigned long i, j, flags, count0, count1, stride0, stride1, addr;
-
+#ifdef XEN
+ /* increment flush clock before mTLB flush */
+ u32 flush_time = tlbflush_clock_inc_and_return();
+#endif
addr = local_cpu_data->ptce_base;
count0 = local_cpu_data->ptce_count[0];
count1 = local_cpu_data->ptce_count[1];
@@ -128,6 +131,10 @@ local_flush_tlb_all (void)
}
local_irq_restore(flags);
ia64_srlz_i(); /* srlz.i implies srlz.d */
+#ifdef XEN
+ /* update after mTLB flush. */
+ tlbflush_update_time(&__get_cpu_var(tlbflush_time), flush_time);
+#endif
}
EXPORT_SYMBOL(local_flush_tlb_all);
diff --git a/xen/arch/ia64/linux-xen/unaligned.c b/xen/arch/ia64/linux-xen/unaligned.c
index 9ef5d42470..86ecbd9374 100644
--- a/xen/arch/ia64/linux-xen/unaligned.c
+++ b/xen/arch/ia64/linux-xen/unaligned.c
@@ -304,7 +304,7 @@ set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, unsigned
unsigned long *bsp, *bspstore, *addr, *rnat_addr;
unsigned long *kbs = (void *) current + IA64_RBS_OFFSET;
unsigned long nat_mask;
- unsigned long old_rsc,new_rsc;
+ unsigned long old_rsc, new_rsc, psr;
unsigned long rnat;
long sof = (regs->cr_ifs) & 0x7f;
long sor = 8 * ((regs->cr_ifs >> 14) & 0xf);
@@ -321,16 +321,17 @@ set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, unsigned
ridx = rotate_reg(sor, rrb_gr, ridx);
old_rsc=ia64_get_rsc();
- new_rsc=old_rsc&(~0x3);
+ /* put RSC to lazy mode, and set loadrs 0 */
+ new_rsc = old_rsc & (~0x3fff0003);
ia64_set_rsc(new_rsc);
+ bsp = kbs + (regs->loadrs >> 19); /* 16 + 3 */
- bspstore = (unsigned long*)ia64_get_bspstore();
- bsp =kbs + (regs->loadrs >> 19);//16+3
-
- addr = ia64_rse_skip_regs(bsp, -sof + ridx);
+ addr = ia64_rse_skip_regs(bsp, -sof + ridx);
nat_mask = 1UL << ia64_rse_slot_num(addr);
- rnat_addr = ia64_rse_rnat_addr(addr);
-
+ rnat_addr = ia64_rse_rnat_addr(addr);
+
+ local_irq_save(psr);
+ bspstore = (unsigned long*)ia64_get_bspstore();
if(addr >= bspstore){
ia64_flushrs ();
@@ -358,6 +359,7 @@ set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, unsigned
ia64_set_bspstore (bspstore);
ia64_set_rnat(rnat);
}
+ local_irq_restore(psr);
ia64_set_rsc(old_rsc);
}
diff --git a/xen/arch/ia64/tools/p2m_expose/Makefile b/xen/arch/ia64/tools/p2m_expose/Makefile
new file mode 100644
index 0000000000..d346326d05
--- /dev/null
+++ b/xen/arch/ia64/tools/p2m_expose/Makefile
@@ -0,0 +1,28 @@
+ifneq ($(KERNELRELEASE),)
+obj-m += expose_p2m.o
+else
+PWD := $(shell pwd)
+TOPDIR ?= $(abspath $(PWD)/../../../../..)
+KDIR ?= $(TOPDIR)/linux-$(shell awk '/^LINUX_VER\>/{print $$3}' $(TOPDIR)/buildconfigs/mk.linux-2.6-xen)-xen
+#CROSS_COMPILE ?= ia64-unknown-linux-
+#ARCH ?= ia64
+
+ifneq ($(O),)
+OPT_O := O=$(realpath $(O))
+endif
+
+ifneq ($(V),)
+OPT_V := V=$(V)
+endif
+
+ifneq ($(ARCH),)
+OPT_ARCH := ARCH=$(ARCH)
+endif
+
+ifneq ($(CROSS_COMPILE),)
+OPT_CORSS_COMPILE := CROSS_COMPILE=$(CROSS_COMPILE)
+endif
+
+default:
+ $(MAKE) -C $(KDIR) $(OPT_O) $(OPT_V) $(OPT_CORSS_COMPILE) $(OPT_ARCH) M=$(PWD)
+endif
diff --git a/xen/arch/ia64/tools/p2m_expose/README.p2m_expose b/xen/arch/ia64/tools/p2m_expose/README.p2m_expose
new file mode 100644
index 0000000000..3b51e11305
--- /dev/null
+++ b/xen/arch/ia64/tools/p2m_expose/README.p2m_expose
@@ -0,0 +1,12 @@
+This directory contains Linux kernel module for p2m exposure test/benchmark.
+
+1. build kernel module
+ - At fist build, linux-xen as usual
+ - then type just 'make' in this directory, then you'll have expose_p2m.ko.
+ See Makefile for details.
+
+2. test, benchmark.
+ - type 'insmod expose_p2m.ko' on the system.
+ Then the result is printed out to your console.
+ insmod fails with EINVAL so that you don't have to execute rmmod.
+
diff --git a/xen/arch/ia64/tools/p2m_expose/expose_p2m.c b/xen/arch/ia64/tools/p2m_expose/expose_p2m.c
new file mode 100644
index 0000000000..26e0b5188e
--- /dev/null
+++ b/xen/arch/ia64/tools/p2m_expose/expose_p2m.c
@@ -0,0 +1,185 @@
+/******************************************************************************
+ * arch/ia64/xen/expose_p2m.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/module.h>
+#include <linux/init.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/hypercall.h>
+#include <asm/hypervisor.h>
+
+#define printd(fmt, ...) printk("%s:%d " fmt, __func__, __LINE__, \
+ ##__VA_ARGS__)
+
+// copied from arch/ia64/mm/tlb.c. it isn't exported.
+void
+local_flush_tlb_all (void)
+{
+ unsigned long i, j, flags, count0, count1, stride0, stride1, addr;
+
+ addr = local_cpu_data->ptce_base;
+ count0 = local_cpu_data->ptce_count[0];
+ count1 = local_cpu_data->ptce_count[1];
+ stride0 = local_cpu_data->ptce_stride[0];
+ stride1 = local_cpu_data->ptce_stride[1];
+
+ local_irq_save(flags);
+ for (i = 0; i < count0; ++i) {
+ for (j = 0; j < count1; ++j) {
+ ia64_ptce(addr);
+ addr += stride1;
+ }
+ addr += stride0;
+ }
+ local_irq_restore(flags);
+ ia64_srlz_i(); /* srlz.i implies srlz.d */
+}
+
+static void
+do_p2m(unsigned long (*conv)(unsigned long),
+ const char* msg, const char* prefix,
+ unsigned long start_gpfn, unsigned end_gpfn, unsigned long stride)
+{
+ struct timeval before_tv;
+ struct timeval after_tv;
+ unsigned long gpfn;
+ unsigned long mfn;
+ unsigned long count;
+ nsec_t nsec;
+
+ count = 0;
+ do_gettimeofday(&before_tv);
+ for (gpfn = start_gpfn; gpfn < end_gpfn; gpfn += stride) {
+ mfn = (*conv)(gpfn);
+ count++;
+ }
+ do_gettimeofday(&after_tv);
+ nsec = timeval_to_ns(&after_tv) - timeval_to_ns(&before_tv);
+ printk("%s stride %4ld %s: %9ld / %6ld = %5ld nsec\n",
+ msg, stride, prefix,
+ nsec, count, nsec/count);
+}
+
+
+static void
+do_with_hypercall(const char* msg,
+ unsigned long start_gpfn, unsigned long end_gpfn,
+ unsigned long stride)
+{
+ do_p2m(&HYPERVISOR_phystomach, msg, "hypercall",
+ start_gpfn, end_gpfn, stride);
+}
+
+static void
+do_with_table(const char* msg,
+ unsigned long start_gpfn, unsigned long end_gpfn,
+ unsigned long stride)
+{
+ do_p2m(&p2m_phystomach, msg, "p2m table",
+ start_gpfn, end_gpfn, stride);
+}
+
+static int __init
+expose_p2m_init(void)
+{
+ unsigned long gpfn;
+ unsigned long mfn;
+ unsigned long p2m_mfn;
+
+ int error_count = 0;
+
+ const int strides[] = {
+ PTRS_PER_PTE, PTRS_PER_PTE/2, PTRS_PER_PTE/3, PTRS_PER_PTE/4,
+ L1_CACHE_BYTES/sizeof(pte_t), 1
+ };
+ int i;
+
+
+#if 0
+ printd("about to call p2m_expose_init()\n");
+ if (p2m_expose_init() < 0) {
+ printd("p2m_expose_init() failed\n");
+ return -EINVAL;
+ }
+ printd("p2m_expose_init() success\n");
+#else
+ if (!p2m_initialized) {
+ printd("p2m exposure isn't initialized\n");
+ return -EINVAL;
+ }
+#endif
+
+ printd("p2m expose test begins\n");
+ for (gpfn = p2m_min_low_pfn; gpfn < p2m_max_low_pfn; gpfn++) {
+ mfn = HYPERVISOR_phystomach(gpfn);
+ p2m_mfn = p2m_phystomach(gpfn);
+ if (mfn != p2m_mfn) {
+ printd("gpfn 0x%016lx "
+ "mfn 0x%016lx p2m_mfn 0x%016lx\n",
+ gpfn, mfn, p2m_mfn);
+ printd("mpaddr 0x%016lx "
+ "maddr 0x%016lx p2m_maddr 0x%016lx\n",
+ gpfn << PAGE_SHIFT,
+ mfn << PAGE_SHIFT, p2m_mfn << PAGE_SHIFT);
+
+ error_count++;
+ if (error_count > 16) {
+ printk("too many errors\n");
+ return -EINVAL;
+ }
+ }
+ }
+ printd("p2m expose test done!\n");
+
+ printk("type "
+ "stride "
+ "type : "
+ " nsec / count = "
+ "nsec per conv\n");
+ for (i = 0; i < sizeof(strides)/sizeof(strides[0]); i++) {
+ int stride = strides[i];
+ local_flush_tlb_all();
+ do_with_hypercall("cold tlb",
+ p2m_min_low_pfn, p2m_max_low_pfn, stride);
+ do_with_hypercall("warm tlb",
+ p2m_min_low_pfn, p2m_max_low_pfn, stride);
+
+ local_flush_tlb_all();
+ do_with_table("cold tlb",
+ p2m_min_low_pfn, p2m_max_low_pfn, stride);
+ do_with_table("warm tlb",
+ p2m_min_low_pfn, p2m_max_low_pfn, stride);
+ }
+
+ return -EINVAL;
+}
+
+static void __exit
+expose_p2m_cleanup(void)
+{
+}
+
+module_init(expose_p2m_init);
+module_exit(expose_p2m_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Isaku Yamahata <yamahata@valinux.co.jp>");
diff --git a/xen/arch/ia64/vmx/Makefile b/xen/arch/ia64/vmx/Makefile
index 9e90d955c9..5be2b4321c 100644
--- a/xen/arch/ia64/vmx/Makefile
+++ b/xen/arch/ia64/vmx/Makefile
@@ -17,3 +17,4 @@ obj-y += vmx_vcpu.o
obj-y += vmx_virt.o
obj-y += vmx_vsa.o
obj-y += vtlb.o
+obj-y += optvfault.o
diff --git a/xen/arch/ia64/vmx/mm.c b/xen/arch/ia64/vmx/mm.c
deleted file mode 100644
index 814df3dd8a..0000000000
--- a/xen/arch/ia64/vmx/mm.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/******************************************************************************
- * arch/ia64/mm.c
- *
- * Copyright (c) 2002-2005 K A Fraser
- * Copyright (c) 2004 Christian Limpach
- * Copyright (c) 2005, Intel Corporation.
- * Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com)
- *
- * 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
- */
-
-/*
- * A description of the x86 page table API:
- *
- * Domains trap to do_mmu_update with a list of update requests.
- * This is a list of (ptr, val) pairs, where the requested operation
- * is *ptr = val.
- *
- * Reference counting of pages:
- * ----------------------------
- * Each page has two refcounts: tot_count and type_count.
- *
- * TOT_COUNT is the obvious reference count. It counts all uses of a
- * physical page frame by a domain, including uses as a page directory,
- * a page table, or simple mappings via a PTE. This count prevents a
- * domain from releasing a frame back to the free pool when it still holds
- * a reference to it.
- *
- * TYPE_COUNT is more subtle. A frame can be put to one of three
- * mutually-exclusive uses: it might be used as a page directory, or a
- * page table, or it may be mapped writable by the domain [of course, a
- * frame may not be used in any of these three ways!].
- * So, type_count is a count of the number of times a frame is being
- * referred to in its current incarnation. Therefore, a page can only
- * change its type when its type count is zero.
- *
- * Pinning the page type:
- * ----------------------
- * The type of a page can be pinned/unpinned with the commands
- * MMUEXT_[UN]PIN_L?_TABLE. Each page can be pinned exactly once (that is,
- * pinning is not reference counted, so it can't be nested).
- * This is useful to prevent a page's type count falling to zero, at which
- * point safety checks would need to be carried out next time the count
- * is increased again.
- *
- * A further note on writable page mappings:
- * -----------------------------------------
- * For simplicity, the count of writable mappings for a page may not
- * correspond to reality. The 'writable count' is incremented for every
- * PTE which maps the page with the _PAGE_RW flag set. However, for
- * write access to be possible the page directory entry must also have
- * its _PAGE_RW bit set. We do not check this as it complicates the
- * reference counting considerably [consider the case of multiple
- * directory entries referencing a single page table, some with the RW
- * bit set, others not -- it starts getting a bit messy].
- * In normal use, this simplification shouldn't be a problem.
- * However, the logic can be added if required.
- *
- * One more note on read-only page mappings:
- * -----------------------------------------
- * We want domains to be able to map pages for read-only access. The
- * main reason is that page tables and directories should be readable
- * by a domain, but it would not be safe for them to be writable.
- * However, domains have free access to rings 1 & 2 of the Intel
- * privilege model. In terms of page protection, these are considered
- * to be part of 'supervisor mode'. The WP bit in CR0 controls whether
- * read-only restrictions are respected in supervisor mode -- if the
- * bit is clear then any mapped page is writable.
- *
- * We get round this by always setting the WP bit and disallowing
- * updates to it. This is very unlikely to cause a problem for guest
- * OS's, which will generally use the WP bit to simplify copy-on-write
- * implementation (in that case, OS wants a fault when it writes to
- * an application-supplied buffer).
- */
-
-#include <xen/config.h>
-//#include <public/xen.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/mm.h>
-#include <xen/errno.h>
-#include <asm/vmx_vcpu.h>
-#include <asm/vmmu.h>
-#include <asm/regionreg.h>
-#include <asm/vmx_mm_def.h>
-/*
- uregs->ptr is virtual address
- uregs->val is pte value
- */
-int vmx_do_mmu_update(mmu_update_t *ureqs,u64 count,u64 *pdone,u64 foreigndom)
-{
- int i,cmd;
- u64 mfn, gpfn;
- VCPU *vcpu;
- mmu_update_t req;
- /* ia64_rr rr; */
- thash_cb_t *hcb;
- /* thash_data_t entry={0},*ovl; */
- vcpu = current;
- /* search_section_t sections; */
- hcb = vmx_vcpu_get_vtlb(vcpu);
- for ( i = 0; i < count; i++ )
- {
- copy_from_user(&req, ureqs, sizeof(req));
- cmd = req.ptr&3;
- req.ptr &= ~3;
-/*
- if(cmd ==MMU_NORMAL_PT_UPDATE){
- entry.page_flags = req.val;
- entry.locked = 1;
- entry.tc = 1;
- entry.cl = DSIDE_TLB;
- rr = vmx_vcpu_rr(vcpu, req.ptr);
- entry.ps = rr.ps;
- entry.key = rr.rid;
- entry.rid = rr.rid;
- entry.vadr = PAGEALIGN(req.ptr,entry.ps);
- sections.tr = 1;
- sections.tc = 0;
- ovl = thash_find_overlap(hcb, &entry, sections);
- if (ovl) {
- // generate MCA.
- panic("Tlb conflict!!");
- return -1;
- }
- thash_purge_and_insert(hcb, &entry, req.ptr);
- }else
- */
- if(cmd == MMU_MACHPHYS_UPDATE){
- mfn = req.ptr >>PAGE_SHIFT;
- gpfn = req.val;
- set_machinetophys(mfn,gpfn);
- }else{
- printf("Unkown command of mmu_update:ptr: %lx,val: %lx \n",req.ptr,req.val);
- while(1);
- }
- ureqs ++;
- }
- return 0;
-}
diff --git a/xen/arch/ia64/vmx/mmio.c b/xen/arch/ia64/vmx/mmio.c
index 95e7ec0351..cca3f7ccb4 100644
--- a/xen/arch/ia64/vmx/mmio.c
+++ b/xen/arch/ia64/vmx/mmio.c
@@ -428,7 +428,7 @@ void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma)
IA64_BUNDLE bundle;
int slot, dir=0, inst_type;
size_t size;
- u64 data, value,post_update, slot1a, slot1b, temp;
+ u64 data, post_update, slot1a, slot1b, temp;
INST64 inst;
regs=vcpu_regs(vcpu);
if (IA64_RETRY == __vmx_get_domain_bundle(regs->cr_iip, &bundle)) {
@@ -454,7 +454,6 @@ void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma)
vcpu_get_gr_nat(vcpu,inst.M4.r2,&data);
}else if((inst.M1.x6>>2)<0xb){ // read
dir=IOREQ_READ;
- vcpu_get_gr_nat(vcpu,inst.M1.r1,&value);
}
}
// Integer Load + Reg update
@@ -462,7 +461,6 @@ void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma)
inst_type = SL_INTEGER;
dir = IOREQ_READ; //write
size = (inst.M2.x6&0x3);
- vcpu_get_gr_nat(vcpu,inst.M2.r1,&value);
vcpu_get_gr_nat(vcpu,inst.M2.r3,&temp);
vcpu_get_gr_nat(vcpu,inst.M2.r2,&post_update);
temp += post_update;
@@ -485,7 +483,6 @@ void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma)
}else if((inst.M3.x6>>2)<0xb){ // read
dir=IOREQ_READ;
- vcpu_get_gr_nat(vcpu,inst.M3.r1,&value);
vcpu_get_gr_nat(vcpu,inst.M3.r3,&temp);
post_update = (inst.M3.i<<7)+inst.M3.imm7;
if(inst.M3.s)
@@ -597,13 +594,6 @@ void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma)
mmio_access(vcpu, padr, &data, size, ma, dir);
}else{
mmio_access(vcpu, padr, &data, size, ma, dir);
- if(size==1)
- data = (value & 0xffffffffffffff00U) | (data & 0xffU);
- else if(size==2)
- data = (value & 0xffffffffffff0000U) | (data & 0xffffU);
- else if(size==4)
- data = (value & 0xffffffff00000000U) | (data & 0xffffffffU);
-
if(inst_type==SL_INTEGER){ //gp
vcpu_set_gr(vcpu,inst.M1.r1,data,0);
}else{
diff --git a/xen/arch/ia64/vmx/optvfault.S b/xen/arch/ia64/vmx/optvfault.S
new file mode 100644
index 0000000000..55f9cd57fb
--- /dev/null
+++ b/xen/arch/ia64/vmx/optvfault.S
@@ -0,0 +1,596 @@
+/*
+ * arch/ia64/vmx/optvfault.S
+ * optimize virtualization fault handler
+ *
+ * Copyright (C) 2006 Intel Co
+ * Xuefei Xu (Anthony Xu) <anthony.xu@intel.com>
+ */
+
+#include <linux/config.h>
+#include <asm/asmmacro.h>
+#include <asm/kregs.h>
+#include <asm/offsets.h>
+#include <asm/percpu.h>
+#include <asm/processor.h>
+#include <asm/vmx_vpd.h>
+#include <asm/vmx_pal_vsa.h>
+#include <asm/asm-offsets.h>
+
+#define ACCE_MOV_FROM_AR
+#define ACCE_MOV_FROM_RR
+#define ACCE_MOV_TO_RR
+
+//mov r1=ar3
+GLOBAL_ENTRY(vmx_asm_mov_from_ar)
+#ifndef ACCE_MOV_FROM_AR
+ br.many vmx_virtualization_fault_back
+#endif
+ add r18=VCPU_VTM_OFFSET_OFS,r21
+ mov r19=ar.itc
+ extr.u r17=r25,6,7
+ ;;
+ ld8 r18=[r18]
+ movl r20=asm_mov_to_reg
+ ;;
+ adds r30=vmx_resume_to_guest-asm_mov_to_reg,r20
+ shladd r17=r17,4,r20
+ mov r24=b0
+ ;;
+ add r19=r19,r18
+ mov b0=r17
+ br.sptk.few b0
+ ;;
+END(vmx_asm_mov_from_ar)
+
+
+// mov r1=rr[r3]
+GLOBAL_ENTRY(vmx_asm_mov_from_rr)
+#ifndef ACCE_MOV_FROM_RR
+ br.many vmx_virtualization_fault_back
+#endif
+ extr.u r16=r25,20,7
+ extr.u r17=r25,6,7
+ movl r20=asm_mov_from_reg
+ ;;
+ adds r30=vmx_asm_mov_from_rr_back_1-asm_mov_from_reg,r20
+ shladd r16=r16,4,r20
+ mov r24=b0
+ ;;
+ add r27=VCPU_VRR0_OFS,r21
+ mov b0=r16
+ br.many b0
+ ;;
+vmx_asm_mov_from_rr_back_1:
+ adds r30=vmx_resume_to_guest-asm_mov_from_reg,r20
+ adds r22=asm_mov_to_reg-asm_mov_from_reg,r20
+ shr.u r26=r19,61
+ ;;
+ shladd r17=r17,4,r22
+ shladd r27=r26,3,r27
+ ;;
+ ld8 r19=[r27]
+ mov b0=r17
+ br.many b0
+END(vmx_asm_mov_from_rr)
+
+
+// mov rr[r3]=r2
+GLOBAL_ENTRY(vmx_asm_mov_to_rr)
+#ifndef ACCE_MOV_TO_RR
+ br.many vmx_virtualization_fault_back
+#endif
+ extr.u r16=r25,20,7
+ extr.u r17=r25,13,7
+ movl r20=asm_mov_from_reg
+ ;;
+ adds r30=vmx_asm_mov_to_rr_back_1-asm_mov_from_reg,r20
+ shladd r16=r16,4,r20
+ mov r22=b0
+ ;;
+ add r27=VCPU_VRR0_OFS,r21
+ mov b0=r16
+ br.many b0
+ ;;
+vmx_asm_mov_to_rr_back_1:
+ adds r30=vmx_asm_mov_to_rr_back_2-asm_mov_from_reg,r20
+ shr.u r23=r19,61
+ shladd r17=r17,4,r20
+ ;;
+ //if rr7, go back
+ cmp.eq p6,p0=7,r23
+ mov b0=r22
+ (p6) br.cond.dpnt.many vmx_virtualization_fault_back
+ ;;
+ mov r28=r19
+ mov b0=r17
+ br.many b0
+vmx_asm_mov_to_rr_back_2:
+ adds r30=vmx_resume_to_guest-asm_mov_from_reg,r20
+ shladd r27=r23,3,r27
+ ;; // +starting_rid
+ st8 [r27]=r19
+ mov b0=r30
+ ;;
+ adds r16=IA64_VCPU_STARTING_RID_OFFSET,r21
+ ;;
+ ld4 r16=[r16]
+ ;;
+ shl r16=r16,8
+ ;;
+ add r19=r19,r16
+ ;; //mangling rid 1 and 3
+ extr.u r16=r19,8,8
+ extr.u r17=r19,24,8
+ extr.u r18=r19,2,6
+ ;;
+ dep r19=r16,r19,24,8
+ ;;
+ dep r19=r17,r19,8,8
+ ;; //set ve 1
+ dep r19=-1,r19,0,1
+ cmp.lt p6,p0=14,r18
+ ;;
+ (p6) mov r18=14
+ ;;
+ (p6) dep r19=r18,r19,2,6
+ ;;
+ cmp.eq p6,p0=0,r23
+ ;;
+ cmp.eq.or p6,p0=4,r23
+ ;;
+ adds r16=IA64_VCPU_MODE_FLAGS_OFFSET,r21
+ (p6) adds r17=IA64_VCPU_META_SAVED_RR0_OFFSET,r21
+ ;;
+ ld4 r16=[r16]
+ cmp.eq p7,p0=r0,r0
+ (p6) shladd r17=r23,1,r17
+ ;;
+ (p6) st8 [r17]=r19
+ (p6) tbit.nz p6,p7=r16,0
+ ;;
+ (p7) mov rr[r28]=r19
+ mov r24=r22
+ br.many b0
+END(vmx_asm_mov_to_rr)
+
+
+#define MOV_TO_REG0 \
+{; \
+ nop.b 0x0; \
+ nop.b 0x0; \
+ nop.b 0x0; \
+ ;; \
+};
+
+
+#define MOV_TO_REG(n) \
+{; \
+ mov r##n##=r19; \
+ mov b0=r30; \
+ br.sptk.many b0; \
+ ;; \
+};
+
+
+#define MOV_FROM_REG(n) \
+{; \
+ mov r19=r##n##; \
+ mov b0=r30; \
+ br.sptk.many b0; \
+ ;; \
+};
+
+
+#define MOV_TO_BANK0_REG(n) \
+ENTRY_MIN_ALIGN(asm_mov_to_bank0_reg##n##); \
+{; \
+ mov r26=r2; \
+ mov r2=r19; \
+ bsw.1; \
+ ;; \
+}; \
+{; \
+ mov r##n##=r2; \
+ nop.b 0x0; \
+ bsw.0; \
+ ;; \
+}; \
+{; \
+ mov r2=r26; \
+ mov b0=r30; \
+ br.sptk.many b0; \
+ ;; \
+}; \
+END(asm_mov_to_bank0_reg##n##)
+
+
+#define MOV_FROM_BANK0_REG(n) \
+ENTRY_MIN_ALIGN(asm_mov_from_bank0_reg##n##); \
+{; \
+ mov r26=r2; \
+ nop.b 0x0; \
+ bsw.1; \
+ ;; \
+}; \
+{; \
+ mov r2=r##n##; \
+ nop.b 0x0; \
+ bsw.0; \
+ ;; \
+}; \
+{; \
+ mov r19=r2; \
+ mov r2=r26; \
+ mov b0=r30; \
+}; \
+{; \
+ nop.b 0x0; \
+ nop.b 0x0; \
+ br.sptk.many b0; \
+ ;; \
+}; \
+END(asm_mov_from_bank0_reg##n##)
+
+
+#define JMP_TO_MOV_TO_BANK0_REG(n) \
+{; \
+ nop.b 0x0; \
+ nop.b 0x0; \
+ br.sptk.many asm_mov_to_bank0_reg##n##; \
+ ;; \
+}
+
+
+#define JMP_TO_MOV_FROM_BANK0_REG(n) \
+{; \
+ nop.b 0x0; \
+ nop.b 0x0; \
+ br.sptk.many asm_mov_from_bank0_reg##n##; \
+ ;; \
+}
+
+
+MOV_FROM_BANK0_REG(16)
+MOV_FROM_BANK0_REG(17)
+MOV_FROM_BANK0_REG(18)
+MOV_FROM_BANK0_REG(19)
+MOV_FROM_BANK0_REG(20)
+MOV_FROM_BANK0_REG(21)
+MOV_FROM_BANK0_REG(22)
+MOV_FROM_BANK0_REG(23)
+MOV_FROM_BANK0_REG(24)
+MOV_FROM_BANK0_REG(25)
+MOV_FROM_BANK0_REG(26)
+MOV_FROM_BANK0_REG(27)
+MOV_FROM_BANK0_REG(28)
+MOV_FROM_BANK0_REG(29)
+MOV_FROM_BANK0_REG(30)
+MOV_FROM_BANK0_REG(31)
+
+
+// mov from reg table
+ENTRY(asm_mov_from_reg)
+ MOV_FROM_REG(0)
+ MOV_FROM_REG(1)
+ MOV_FROM_REG(2)
+ MOV_FROM_REG(3)
+ MOV_FROM_REG(4)
+ MOV_FROM_REG(5)
+ MOV_FROM_REG(6)
+ MOV_FROM_REG(7)
+ MOV_FROM_REG(8)
+ MOV_FROM_REG(9)
+ MOV_FROM_REG(10)
+ MOV_FROM_REG(11)
+ MOV_FROM_REG(12)
+ MOV_FROM_REG(13)
+ MOV_FROM_REG(14)
+ MOV_FROM_REG(15)
+ JMP_TO_MOV_FROM_BANK0_REG(16)
+ JMP_TO_MOV_FROM_BANK0_REG(17)
+ JMP_TO_MOV_FROM_BANK0_REG(18)
+ JMP_TO_MOV_FROM_BANK0_REG(19)
+ JMP_TO_MOV_FROM_BANK0_REG(20)
+ JMP_TO_MOV_FROM_BANK0_REG(21)
+ JMP_TO_MOV_FROM_BANK0_REG(22)
+ JMP_TO_MOV_FROM_BANK0_REG(23)
+ JMP_TO_MOV_FROM_BANK0_REG(24)
+ JMP_TO_MOV_FROM_BANK0_REG(25)
+ JMP_TO_MOV_FROM_BANK0_REG(26)
+ JMP_TO_MOV_FROM_BANK0_REG(27)
+ JMP_TO_MOV_FROM_BANK0_REG(28)
+ JMP_TO_MOV_FROM_BANK0_REG(29)
+ JMP_TO_MOV_FROM_BANK0_REG(30)
+ JMP_TO_MOV_FROM_BANK0_REG(31)
+ MOV_FROM_REG(32)
+ MOV_FROM_REG(33)
+ MOV_FROM_REG(34)
+ MOV_FROM_REG(35)
+ MOV_FROM_REG(36)
+ MOV_FROM_REG(37)
+ MOV_FROM_REG(38)
+ MOV_FROM_REG(39)
+ MOV_FROM_REG(40)
+ MOV_FROM_REG(41)
+ MOV_FROM_REG(42)
+ MOV_FROM_REG(43)
+ MOV_FROM_REG(44)
+ MOV_FROM_REG(45)
+ MOV_FROM_REG(46)
+ MOV_FROM_REG(47)
+ MOV_FROM_REG(48)
+ MOV_FROM_REG(49)
+ MOV_FROM_REG(50)
+ MOV_FROM_REG(51)
+ MOV_FROM_REG(52)
+ MOV_FROM_REG(53)
+ MOV_FROM_REG(54)
+ MOV_FROM_REG(55)
+ MOV_FROM_REG(56)
+ MOV_FROM_REG(57)
+ MOV_FROM_REG(58)
+ MOV_FROM_REG(59)
+ MOV_FROM_REG(60)
+ MOV_FROM_REG(61)
+ MOV_FROM_REG(62)
+ MOV_FROM_REG(63)
+ MOV_FROM_REG(64)
+ MOV_FROM_REG(65)
+ MOV_FROM_REG(66)
+ MOV_FROM_REG(67)
+ MOV_FROM_REG(68)
+ MOV_FROM_REG(69)
+ MOV_FROM_REG(70)
+ MOV_FROM_REG(71)
+ MOV_FROM_REG(72)
+ MOV_FROM_REG(73)
+ MOV_FROM_REG(74)
+ MOV_FROM_REG(75)
+ MOV_FROM_REG(76)
+ MOV_FROM_REG(77)
+ MOV_FROM_REG(78)
+ MOV_FROM_REG(79)
+ MOV_FROM_REG(80)
+ MOV_FROM_REG(81)
+ MOV_FROM_REG(82)
+ MOV_FROM_REG(83)
+ MOV_FROM_REG(84)
+ MOV_FROM_REG(85)
+ MOV_FROM_REG(86)
+ MOV_FROM_REG(87)
+ MOV_FROM_REG(88)
+ MOV_FROM_REG(89)
+ MOV_FROM_REG(90)
+ MOV_FROM_REG(91)
+ MOV_FROM_REG(92)
+ MOV_FROM_REG(93)
+ MOV_FROM_REG(94)
+ MOV_FROM_REG(95)
+ MOV_FROM_REG(96)
+ MOV_FROM_REG(97)
+ MOV_FROM_REG(98)
+ MOV_FROM_REG(99)
+ MOV_FROM_REG(100)
+ MOV_FROM_REG(101)
+ MOV_FROM_REG(102)
+ MOV_FROM_REG(103)
+ MOV_FROM_REG(104)
+ MOV_FROM_REG(105)
+ MOV_FROM_REG(106)
+ MOV_FROM_REG(107)
+ MOV_FROM_REG(108)
+ MOV_FROM_REG(109)
+ MOV_FROM_REG(110)
+ MOV_FROM_REG(111)
+ MOV_FROM_REG(112)
+ MOV_FROM_REG(113)
+ MOV_FROM_REG(114)
+ MOV_FROM_REG(115)
+ MOV_FROM_REG(116)
+ MOV_FROM_REG(117)
+ MOV_FROM_REG(118)
+ MOV_FROM_REG(119)
+ MOV_FROM_REG(120)
+ MOV_FROM_REG(121)
+ MOV_FROM_REG(122)
+ MOV_FROM_REG(123)
+ MOV_FROM_REG(124)
+ MOV_FROM_REG(125)
+ MOV_FROM_REG(126)
+ MOV_FROM_REG(127)
+END(asm_mov_from_reg)
+
+
+/* must be in bank 0
+ * parameter:
+ * r31: pr
+ * r24: b0
+ */
+ENTRY(vmx_resume_to_guest)
+ mov r16=cr.ipsr
+ movl r20=__vsa_base
+ ;;
+ ld8 r20=[r20]
+ adds r19=IA64_VPD_BASE_OFFSET,r21
+ ;;
+ ld8 r25=[r19]
+ extr.u r17=r16,IA64_PSR_RI_BIT,2
+ tbit.nz p6,p7=r16,IA64_PSR_RI_BIT+1
+ ;;
+ (p6) mov r18=cr.iip
+ (p6) mov r17=r0
+ ;;
+ (p6) add r18=0x10,r18
+ (p7) add r17=1,r17
+ ;;
+ (p6) mov cr.iip=r18
+ dep r16=r17,r16,IA64_PSR_RI_BIT,2
+ ;;
+ mov cr.ipsr=r16
+ adds r19= VPD_VPSR_START_OFFSET,r25
+ add r28=PAL_VPS_RESUME_NORMAL,r20
+ add r29=PAL_VPS_RESUME_HANDLER,r20
+ ;;
+ ld8 r19=[r19]
+ mov b0=r29
+ cmp.ne p6,p7 = r0,r0
+ ;;
+ tbit.z p6,p7 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic
+ ;;
+ (p6) ld8 r26=[r25]
+ (p7) mov b0=r28
+ mov pr=r31,-2
+ br.sptk.many b0 // call pal service
+ ;;
+END(vmx_resume_to_guest)
+
+
+MOV_TO_BANK0_REG(16)
+MOV_TO_BANK0_REG(17)
+MOV_TO_BANK0_REG(18)
+MOV_TO_BANK0_REG(19)
+MOV_TO_BANK0_REG(20)
+MOV_TO_BANK0_REG(21)
+MOV_TO_BANK0_REG(22)
+MOV_TO_BANK0_REG(23)
+MOV_TO_BANK0_REG(24)
+MOV_TO_BANK0_REG(25)
+MOV_TO_BANK0_REG(26)
+MOV_TO_BANK0_REG(27)
+MOV_TO_BANK0_REG(28)
+MOV_TO_BANK0_REG(29)
+MOV_TO_BANK0_REG(30)
+MOV_TO_BANK0_REG(31)
+
+
+// mov to reg table
+ENTRY(asm_mov_to_reg)
+ MOV_TO_REG0
+ MOV_TO_REG(1)
+ MOV_TO_REG(2)
+ MOV_TO_REG(3)
+ MOV_TO_REG(4)
+ MOV_TO_REG(5)
+ MOV_TO_REG(6)
+ MOV_TO_REG(7)
+ MOV_TO_REG(8)
+ MOV_TO_REG(9)
+ MOV_TO_REG(10)
+ MOV_TO_REG(11)
+ MOV_TO_REG(12)
+ MOV_TO_REG(13)
+ MOV_TO_REG(14)
+ MOV_TO_REG(15)
+ JMP_TO_MOV_TO_BANK0_REG(16)
+ JMP_TO_MOV_TO_BANK0_REG(17)
+ JMP_TO_MOV_TO_BANK0_REG(18)
+ JMP_TO_MOV_TO_BANK0_REG(19)
+ JMP_TO_MOV_TO_BANK0_REG(20)
+ JMP_TO_MOV_TO_BANK0_REG(21)
+ JMP_TO_MOV_TO_BANK0_REG(22)
+ JMP_TO_MOV_TO_BANK0_REG(23)
+ JMP_TO_MOV_TO_BANK0_REG(24)
+ JMP_TO_MOV_TO_BANK0_REG(25)
+ JMP_TO_MOV_TO_BANK0_REG(26)
+ JMP_TO_MOV_TO_BANK0_REG(27)
+ JMP_TO_MOV_TO_BANK0_REG(28)
+ JMP_TO_MOV_TO_BANK0_REG(29)
+ JMP_TO_MOV_TO_BANK0_REG(30)
+ JMP_TO_MOV_TO_BANK0_REG(31)
+ MOV_TO_REG(32)
+ MOV_TO_REG(33)
+ MOV_TO_REG(34)
+ MOV_TO_REG(35)
+ MOV_TO_REG(36)
+ MOV_TO_REG(37)
+ MOV_TO_REG(38)
+ MOV_TO_REG(39)
+ MOV_TO_REG(40)
+ MOV_TO_REG(41)
+ MOV_TO_REG(42)
+ MOV_TO_REG(43)
+ MOV_TO_REG(44)
+ MOV_TO_REG(45)
+ MOV_TO_REG(46)
+ MOV_TO_REG(47)
+ MOV_TO_REG(48)
+ MOV_TO_REG(49)
+ MOV_TO_REG(50)
+ MOV_TO_REG(51)
+ MOV_TO_REG(52)
+ MOV_TO_REG(53)
+ MOV_TO_REG(54)
+ MOV_TO_REG(55)
+ MOV_TO_REG(56)
+ MOV_TO_REG(57)
+ MOV_TO_REG(58)
+ MOV_TO_REG(59)
+ MOV_TO_REG(60)
+ MOV_TO_REG(61)
+ MOV_TO_REG(62)
+ MOV_TO_REG(63)
+ MOV_TO_REG(64)
+ MOV_TO_REG(65)
+ MOV_TO_REG(66)
+ MOV_TO_REG(67)
+ MOV_TO_REG(68)
+ MOV_TO_REG(69)
+ MOV_TO_REG(70)
+ MOV_TO_REG(71)
+ MOV_TO_REG(72)
+ MOV_TO_REG(73)
+ MOV_TO_REG(74)
+ MOV_TO_REG(75)
+ MOV_TO_REG(76)
+ MOV_TO_REG(77)
+ MOV_TO_REG(78)
+ MOV_TO_REG(79)
+ MOV_TO_REG(80)
+ MOV_TO_REG(81)
+ MOV_TO_REG(82)
+ MOV_TO_REG(83)
+ MOV_TO_REG(84)
+ MOV_TO_REG(85)
+ MOV_TO_REG(86)
+ MOV_TO_REG(87)
+ MOV_TO_REG(88)
+ MOV_TO_REG(89)
+ MOV_TO_REG(90)
+ MOV_TO_REG(91)
+ MOV_TO_REG(92)
+ MOV_TO_REG(93)
+ MOV_TO_REG(94)
+ MOV_TO_REG(95)
+ MOV_TO_REG(96)
+ MOV_TO_REG(97)
+ MOV_TO_REG(98)
+ MOV_TO_REG(99)
+ MOV_TO_REG(100)
+ MOV_TO_REG(101)
+ MOV_TO_REG(102)
+ MOV_TO_REG(103)
+ MOV_TO_REG(104)
+ MOV_TO_REG(105)
+ MOV_TO_REG(106)
+ MOV_TO_REG(107)
+ MOV_TO_REG(108)
+ MOV_TO_REG(109)
+ MOV_TO_REG(110)
+ MOV_TO_REG(111)
+ MOV_TO_REG(112)
+ MOV_TO_REG(113)
+ MOV_TO_REG(114)
+ MOV_TO_REG(115)
+ MOV_TO_REG(116)
+ MOV_TO_REG(117)
+ MOV_TO_REG(118)
+ MOV_TO_REG(119)
+ MOV_TO_REG(120)
+ MOV_TO_REG(121)
+ MOV_TO_REG(122)
+ MOV_TO_REG(123)
+ MOV_TO_REG(124)
+ MOV_TO_REG(125)
+ MOV_TO_REG(126)
+ MOV_TO_REG(127)
+END(asm_mov_to_reg)
diff --git a/xen/arch/ia64/vmx/pal_emul.c b/xen/arch/ia64/vmx/pal_emul.c
index 2c88fb34e2..8f3c9400d4 100644
--- a/xen/arch/ia64/vmx/pal_emul.c
+++ b/xen/arch/ia64/vmx/pal_emul.c
@@ -17,509 +17,46 @@
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
-
-#include <asm/vmx_vcpu.h>
+
+#include <xen/lib.h>
+#include <asm/vcpu.h>
+#include <asm/dom_fw.h>
#include <asm/pal.h>
#include <asm/sal.h>
-#include <asm/dom_fw.h>
-#include <asm/tlb.h>
-#include <asm/vmx_mm_def.h>
-#include <xen/hypercall.h>
-#include <public/sched.h>
-
-/*
- * Handy macros to make sure that the PAL return values start out
- * as something meaningful.
- */
-#define INIT_PAL_STATUS_UNIMPLEMENTED(x) \
- { \
- x.status = PAL_STATUS_UNIMPLEMENTED; \
- x.v0 = 0; \
- x.v1 = 0; \
- x.v2 = 0; \
- }
-
-#define INIT_PAL_STATUS_SUCCESS(x) \
- { \
- x.status = PAL_STATUS_SUCCESS; \
- x.v0 = 0; \
- x.v1 = 0; \
- x.v2 = 0; \
- }
-
-static void
-get_pal_parameters(VCPU *vcpu, UINT64 *gr29, UINT64 *gr30, UINT64 *gr31) {
-
- vcpu_get_gr_nat(vcpu,29,gr29);
- vcpu_get_gr_nat(vcpu,30,gr30);
- vcpu_get_gr_nat(vcpu,31,gr31);
-}
-
-static void
-set_pal_result(VCPU *vcpu,struct ia64_pal_retval result) {
-
- vcpu_set_gr(vcpu,8, result.status,0);
- vcpu_set_gr(vcpu,9, result.v0,0);
- vcpu_set_gr(vcpu,10, result.v1,0);
- vcpu_set_gr(vcpu,11, result.v2,0);
-}
-
-static void
-set_sal_result(VCPU *vcpu,struct sal_ret_values result) {
-
- vcpu_set_gr(vcpu,8, result.r8,0);
- vcpu_set_gr(vcpu,9, result.r9,0);
- vcpu_set_gr(vcpu,10, result.r10,0);
- vcpu_set_gr(vcpu,11, result.r11,0);
-}
-
-static struct ia64_pal_retval
-pal_cache_flush(VCPU *vcpu) {
- UINT64 gr28,gr29, gr30, gr31;
- struct ia64_pal_retval result;
-
- get_pal_parameters(vcpu, &gr29, &gr30, &gr31);
- vcpu_get_gr_nat(vcpu, 28, &gr28);
-
- /* Always call Host Pal in int=1 */
- gr30 = gr30 & ~0x2UL;
-
- /*
- * Call Host PAL cache flush
- * Clear psr.ic when call PAL_CACHE_FLUSH
- */
- result = ia64_pal_call_static(gr28 ,gr29, gr30, gr31, 1);
-
- /* If host PAL call is interrupted, then loop to complete it */
-// while (result.status == 1)
-// ia64_pal_call_static(gr28 ,gr29, gr30, result.v1, 1LL);
-//
- if (result.status != 0)
- panic_domain(vcpu_regs(vcpu), "PAL_CACHE_FLUSH ERROR, "
- "status %ld", result.status);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_vm_tr_read(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_prefetch_visibility(VCPU *vcpu) {
- /* Due to current MM virtualization algorithm,
- * We do not allow guest to change mapping attribute.
- * Thus we will not support PAL_PREFETCH_VISIBILITY
- */
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_platform_addr(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_SUCCESS(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_halt(VCPU *vcpu) {
- //bugbug: to be implement.
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_halt_light(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- if (!is_unmasked_irq(vcpu))
- do_sched_op_compat(SCHEDOP_block, 0);
-
- INIT_PAL_STATUS_SUCCESS(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_cache_read(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_cache_write(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_bus_get_features(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_cache_summary(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_cache_init(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_SUCCESS(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_cache_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_cache_prot_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_mem_attrib(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_debug_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_fixed_addr(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_freq_base(VCPU *vcpu) {
- struct ia64_pal_retval result;
- struct ia64_sal_retval isrv;
-
- PAL_CALL(result,PAL_FREQ_BASE, 0, 0, 0);
- /*
- * PAL_FREQ_BASE may not be implemented in some platforms,
- * call SAL instead.
- */
- if (result.v0 == 0) {
- SAL_CALL(isrv, SAL_FREQ_BASE,
- SAL_FREQ_BASE_PLATFORM, 0, 0, 0, 0, 0, 0);
- result.status = isrv.status;
- result.v0 = isrv.v0;
- result.v1 = result.v2 = 0;
- }
- return result;
-}
-
-static struct ia64_pal_retval
-pal_freq_ratios(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- PAL_CALL(result, PAL_FREQ_RATIOS, 0, 0, 0);
- return result;
-}
-
-static struct ia64_pal_retval
-pal_halt_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_logical_to_physica(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_perf_mon_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_proc_get_features(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_ptce_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_register_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_rse_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_test_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_vm_summary(VCPU *vcpu) {
- pal_vm_info_1_u_t vminfo1;
- pal_vm_info_2_u_t vminfo2;
- struct ia64_pal_retval result;
-
- PAL_CALL(result, PAL_VM_SUMMARY, 0, 0, 0);
- if (!result.status) {
- vminfo1.pvi1_val = result.v0;
- vminfo1.pal_vm_info_1_s.max_itr_entry = NITRS -1;
- vminfo1.pal_vm_info_1_s.max_dtr_entry = NDTRS -1;
- result.v0 = vminfo1.pvi1_val;
- vminfo2.pal_vm_info_2_s.impl_va_msb = GUEST_IMPL_VA_MSB;
- vminfo2.pal_vm_info_2_s.rid_size =
- current->domain->arch.rid_bits;
- result.v1 = vminfo2.pvi2_val;
- }
- return result;
-}
-
-static struct ia64_pal_retval
-pal_vm_info(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
-
-static struct ia64_pal_retval
-pal_vm_page_size(VCPU *vcpu) {
- struct ia64_pal_retval result;
-
- INIT_PAL_STATUS_UNIMPLEMENTED(result);
-
- return result;
-}
void
-pal_emul(VCPU *vcpu) {
- UINT64 gr28;
+pal_emul(struct vcpu *vcpu)
+{
+ u64 gr28, gr29, gr30, gr31;
struct ia64_pal_retval result;
- vcpu_get_gr_nat(vcpu,28,&gr28); //bank1
-
- perfc_incrc(vmx_pal_emul);
- switch (gr28) {
- case PAL_CACHE_FLUSH:
- result = pal_cache_flush(vcpu);
- break;
-
- case PAL_PREFETCH_VISIBILITY:
- result = pal_prefetch_visibility(vcpu);
- break;
-
- case PAL_VM_TR_READ:
- result = pal_vm_tr_read(vcpu);
- break;
-
- case PAL_HALT:
- result = pal_halt(vcpu);
- break;
-
- case PAL_HALT_LIGHT:
- result = pal_halt_light(vcpu);
- break;
-
- case PAL_CACHE_READ:
- result = pal_cache_read(vcpu);
- break;
+ vcpu_get_gr_nat(vcpu, 28, &gr28); //bank1
- case PAL_CACHE_WRITE:
- result = pal_cache_write(vcpu);
- break;
+ /* FIXME: works only for static calling convention ? */
+ vcpu_get_gr_nat(vcpu, 29, &gr29);
+ vcpu_get_gr_nat(vcpu, 30, &gr30);
+ vcpu_get_gr_nat(vcpu, 31, &gr31);
- case PAL_PLATFORM_ADDR:
- result = pal_platform_addr(vcpu);
- break;
-
- case PAL_FREQ_RATIOS:
- result = pal_freq_ratios(vcpu);
- break;
-
- case PAL_FREQ_BASE:
- result = pal_freq_base(vcpu);
- break;
-
- case PAL_BUS_GET_FEATURES :
- result = pal_bus_get_features(vcpu);
- break;
-
- case PAL_CACHE_SUMMARY :
- result = pal_cache_summary(vcpu);
- break;
-
- case PAL_CACHE_INIT :
- result = pal_cache_init(vcpu);
- break;
-
- case PAL_CACHE_INFO :
- result = pal_cache_info(vcpu);
- break;
-
- case PAL_CACHE_PROT_INFO :
- result = pal_cache_prot_info(vcpu);
- break;
-
- case PAL_MEM_ATTRIB :
- result = pal_mem_attrib(vcpu);
- break;
-
- case PAL_DEBUG_INFO :
- result = pal_debug_info(vcpu);
- break;
-
- case PAL_FIXED_ADDR :
- result = pal_fixed_addr(vcpu);
- break;
-
- case PAL_HALT_INFO :
- result = pal_halt_info(vcpu);
- break;
-
- case PAL_LOGICAL_TO_PHYSICAL :
- result = pal_logical_to_physica(vcpu);
- break;
-
- case PAL_PERF_MON_INFO :
- result = pal_perf_mon_info(vcpu);
- break;
-
- case PAL_PROC_GET_FEATURES:
- result = pal_proc_get_features(vcpu);
- break;
-
- case PAL_PTCE_INFO :
- result = pal_ptce_info(vcpu);
- break;
-
- case PAL_REGISTER_INFO :
- result = pal_register_info(vcpu);
- break;
-
- case PAL_RSE_INFO :
- result = pal_rse_info(vcpu);
- break;
-
- case PAL_TEST_PROC :
- result = pal_test_info(vcpu);
- break;
-
- case PAL_VM_SUMMARY :
- result = pal_vm_summary(vcpu);
- break;
-
- case PAL_VM_INFO :
- result = pal_vm_info(vcpu);
- break;
-
- case PAL_VM_PAGE_SIZE :
- result = pal_vm_page_size(vcpu);
- break;
+ perfc_incrc(vmx_pal_emul);
+ result = xen_pal_emulator(gr28, gr29, gr30, gr31);
- default:
- panic_domain(vcpu_regs(vcpu),"pal_emul(): guest "
- "call unsupported pal" );
- }
- set_pal_result(vcpu, result);
+ vcpu_set_gr(vcpu, 8, result.status, 0);
+ vcpu_set_gr(vcpu, 9, result.v0, 0);
+ vcpu_set_gr(vcpu, 10, result.v1, 0);
+ vcpu_set_gr(vcpu, 11, result.v2, 0);
}
void
-sal_emul(VCPU *v) {
+sal_emul(struct vcpu *v)
+{
struct sal_ret_values result;
result = sal_emulator(vcpu_get_gr(v, 32), vcpu_get_gr(v, 33),
vcpu_get_gr(v, 34), vcpu_get_gr(v, 35),
vcpu_get_gr(v, 36), vcpu_get_gr(v, 37),
vcpu_get_gr(v, 38), vcpu_get_gr(v, 39));
- set_sal_result(v, result);
+
+ vcpu_set_gr(v, 8, result.r8, 0);
+ vcpu_set_gr(v, 9, result.r9, 0);
+ vcpu_set_gr(v, 10, result.r10, 0);
+ vcpu_set_gr(v, 11, result.r11, 0);
}
diff --git a/xen/arch/ia64/vmx/vlsapic.c b/xen/arch/ia64/vmx/vlsapic.c
index 0bc909f127..5ab03e4730 100644
--- a/xen/arch/ia64/vmx/vlsapic.c
+++ b/xen/arch/ia64/vmx/vlsapic.c
@@ -49,14 +49,67 @@
* Update the checked last_itc.
*/
-extern void vmx_reflect_interruption(UINT64 ifa,UINT64 isr,UINT64 iim,
- UINT64 vector,REGS *regs);
+extern void vmx_reflect_interruption(u64 ifa, u64 isr, u64 iim,
+ u64 vector, REGS *regs);
static void update_last_itc(vtime_t *vtm, uint64_t cur_itc)
{
vtm->last_itc = cur_itc;
}
/*
+ * Next for vLSapic
+ */
+
+#define NMI_VECTOR 2
+#define ExtINT_VECTOR 0
+#define NULL_VECTOR -1
+
+static void update_vhpi(VCPU *vcpu, int vec)
+{
+ u64 vhpi;
+
+ if (vec == NULL_VECTOR)
+ vhpi = 0;
+ else if (vec == NMI_VECTOR)
+ vhpi = 32;
+ else if (vec == ExtINT_VECTOR)
+ vhpi = 16;
+ else
+ vhpi = vec >> 4;
+
+ VCPU(vcpu,vhpi) = vhpi;
+ // TODO: Add support for XENO
+ if (VCPU(vcpu,vac).a_int)
+ ia64_call_vsa(PAL_VPS_SET_PENDING_INTERRUPT,
+ (uint64_t)vcpu->arch.privregs, 0, 0, 0, 0, 0, 0);
+}
+
+
+/*
+ * May come from virtualization fault or
+ * nested host interrupt.
+ */
+static int vmx_vcpu_unpend_interrupt(VCPU *vcpu, uint8_t vector)
+{
+ uint64_t spsr;
+ int ret;
+
+ if (vector & ~0xff) {
+ DPRINTK("vmx_vcpu_pend_interrupt: bad vector\n");
+ return -1;
+ }
+
+ local_irq_save(spsr);
+ ret = test_and_clear_bit(vector, &VCPU(vcpu, irr[0]));
+ local_irq_restore(spsr);
+
+ if (ret)
+ vcpu->arch.irq_new_pending = 1;
+
+ return ret;
+}
+
+/*
* ITC value saw in guest (host+offset+drift).
*/
static uint64_t now_itc(vtime_t *vtm)
@@ -107,9 +160,6 @@ static void vtm_timer_fn(void *data)
}
vtm=&(vcpu->arch.arch_vmx.vtm);
cur_itc = now_itc(vtm);
- // vitm =VCPU(vcpu, itm);
- //fire_itc2 = cur_itc;
- //fire_itm2 = vitm;
update_last_itc(vtm,cur_itc); // pseudo read to update vITC
}
@@ -137,6 +187,7 @@ uint64_t vtm_get_itc(VCPU *vcpu)
vtm=&(vcpu->arch.arch_vmx.vtm);
guest_itc = now_itc(vtm);
+ update_last_itc(vtm, guest_itc); // update vITC
return guest_itc;
}
@@ -158,7 +209,7 @@ void vtm_set_itc(VCPU *vcpu, uint64_t new_itc)
vtm->last_itc = new_itc;
}
if(vitm < new_itc){
- clear_bit(ITV_VECTOR(vitv), &VCPU(vcpu, irr[0]));
+ vmx_vcpu_unpend_interrupt(vcpu, ITV_VECTOR(vitv));
stop_timer(&vtm->vtm_timer);
}
}
@@ -175,12 +226,12 @@ void vtm_set_itm(VCPU *vcpu, uint64_t val)
vitv = VCPU(vcpu, itv);
vtm=&(vcpu->arch.arch_vmx.vtm);
// TODO; need to handle VHPI in future
- clear_bit(ITV_VECTOR(vitv), &VCPU(vcpu, irr[0]));
+ vmx_vcpu_unpend_interrupt(vcpu, ITV_VECTOR(vitv));
VCPU(vcpu,itm)=val;
- cur_itc =now_itc(vtm);
- if(time_before(val, cur_itc))
- val = cur_itc;
- if(val > vtm->last_itc){
+ if (val >= vtm->last_itc) {
+ cur_itc = now_itc(vtm);
+ if (time_before(val, cur_itc))
+ val = cur_itc;
expires = NOW() + cycle_to_ns(val-cur_itc) + TIMER_SLOP;
set_timer(&vtm->vtm_timer, expires);
}else{
@@ -195,10 +246,10 @@ void vtm_set_itv(VCPU *vcpu, uint64_t val)
olditv = VCPU(vcpu, itv);
VCPU(vcpu, itv) = val;
if(ITV_IRQ_MASK(val)){
- clear_bit(ITV_VECTOR(olditv), &VCPU(vcpu, irr[0]));
+ vmx_vcpu_unpend_interrupt(vcpu, ITV_VECTOR(olditv));
}else if(ITV_VECTOR(olditv)!=ITV_VECTOR(val)){
- if(test_and_clear_bit(ITV_VECTOR(olditv), &VCPU(vcpu, irr[0])))
- set_bit(ITV_VECTOR(val), &VCPU(vcpu, irr[0]));
+ if (vmx_vcpu_unpend_interrupt(vcpu, ITV_VECTOR(olditv)))
+ vmx_vcpu_pend_interrupt(vcpu, ITV_VECTOR(val));
}
}
@@ -272,36 +323,6 @@ void vtm_domain_in(VCPU *vcpu)
}
*/
-/*
- * Next for vLSapic
- */
-
-#define NMI_VECTOR 2
-#define ExtINT_VECTOR 0
-#define NULL_VECTOR -1
-static void update_vhpi(VCPU *vcpu, int vec)
-{
- u64 vhpi;
- if ( vec == NULL_VECTOR ) {
- vhpi = 0;
- }
- else if ( vec == NMI_VECTOR ) { // NMI
- vhpi = 32;
- } else if (vec == ExtINT_VECTOR) { //ExtINT
- vhpi = 16;
- }
- else {
- vhpi = vec >> 4;
- }
-
- VCPU(vcpu,vhpi) = vhpi;
- // TODO: Add support for XENO
- if ( VCPU(vcpu,vac).a_int ) {
- ia64_call_vsa ( PAL_VPS_SET_PENDING_INTERRUPT,
- (uint64_t) &(vcpu->arch.privregs), 0, 0,0,0,0,0);
- }
-}
-
#ifdef V_IOSAPIC_READY
/* Assist to check virtual interrupt lines */
void vmx_virq_line_assist(struct vcpu *v)
@@ -524,16 +545,20 @@ int vmx_vcpu_pend_interrupt(VCPU *vcpu, uint8_t vector)
local_irq_save(spsr);
ret = test_and_set_bit(vector, &VCPU(vcpu, irr[0]));
local_irq_restore(spsr);
- vcpu->arch.irq_new_pending = 1;
+
+ if (!ret)
+ vcpu->arch.irq_new_pending = 1;
+
return ret;
}
+
/*
* Add batch of pending interrupt.
* The interrupt source is contained in pend_irr[0-3] with
* each bits stand for one interrupt.
*/
-void vmx_vcpu_pend_batch_interrupt(VCPU *vcpu, UINT64 *pend_irr)
+void vmx_vcpu_pend_batch_interrupt(VCPU *vcpu, u64 *pend_irr)
{
uint64_t spsr;
int i;
@@ -559,14 +584,13 @@ void vmx_vcpu_pend_batch_interrupt(VCPU *vcpu, UINT64 *pend_irr)
*/
int vmx_check_pending_irq(VCPU *vcpu)
{
- uint64_t spsr, mask;
- int h_pending, h_inservice;
- uint64_t isr;
- IA64_PSR vpsr;
+ int mask, h_pending, h_inservice;
+ uint64_t isr;
+ IA64_PSR vpsr;
REGS *regs=vcpu_regs(vcpu);
- local_irq_save(spsr);
h_pending = highest_pending_irq(vcpu);
if ( h_pending == NULL_VECTOR ) {
+ update_vhpi(vcpu, NULL_VECTOR);
h_pending = SPURIOUS_VECTOR;
goto chk_irq_exit;
}
@@ -578,13 +602,11 @@ int vmx_check_pending_irq(VCPU *vcpu)
isr = vpsr.val & IA64_PSR_RI;
if ( !vpsr.ic )
panic_domain(regs,"Interrupt when IC=0\n");
+ update_vhpi(vcpu, h_pending);
+ vmx_reflect_interruption(0, isr, 0, 12, regs); // EXT IRQ
+ } else if (mask == IRQ_MASKED_BY_INSVC) {
if (VCPU(vcpu, vhpi))
update_vhpi(vcpu, NULL_VECTOR);
- vmx_reflect_interruption(0,isr,0, 12, regs ); // EXT IRQ
- }
- else if ( mask == IRQ_MASKED_BY_INSVC ) {
- // cann't inject VHPI
-// DPRINTK("IRQ masked by higher inservice\n");
}
else {
// masked by vpsr.i or vtpr.
@@ -592,7 +614,6 @@ int vmx_check_pending_irq(VCPU *vcpu)
}
chk_irq_exit:
- local_irq_restore(spsr);
return h_pending;
}
@@ -602,17 +623,13 @@ chk_irq_exit:
void guest_write_eoi(VCPU *vcpu)
{
int vec;
- uint64_t spsr;
vec = highest_inservice_irq(vcpu);
if ( vec == NULL_VECTOR )
- panic_domain(vcpu_regs(vcpu),"Wrong vector to EOI\n");
- local_irq_save(spsr);
+ panic_domain(vcpu_regs(vcpu), "Wrong vector to EOI\n");
VLSAPIC_INSVC(vcpu,vec>>6) &= ~(1UL <<(vec&63));
- local_irq_restore(spsr);
VCPU(vcpu, eoi)=0; // overwrite the data
vcpu->arch.irq_new_pending=1;
-// vmx_check_pending_irq(vcpu);
}
int is_unmasked_irq(VCPU *vcpu)
@@ -631,23 +648,21 @@ int is_unmasked_irq(VCPU *vcpu)
uint64_t guest_read_vivr(VCPU *vcpu)
{
- int vec, h_inservice;
- uint64_t spsr;
-
- local_irq_save(spsr);
+ int vec, h_inservice, mask;
vec = highest_pending_irq(vcpu);
h_inservice = highest_inservice_irq(vcpu);
- if ( vec == NULL_VECTOR ||
- irq_masked(vcpu, vec, h_inservice) != IRQ_NO_MASKED ) {
- local_irq_restore(spsr);
+ mask = irq_masked(vcpu, vec, h_inservice);
+ if (vec == NULL_VECTOR || mask == IRQ_MASKED_BY_INSVC) {
+ if (VCPU(vcpu, vhpi))
+ update_vhpi(vcpu, NULL_VECTOR);
+ return IA64_SPURIOUS_INT_VECTOR;
+ }
+ if (mask == IRQ_MASKED_BY_VTPR) {
+ update_vhpi(vcpu, vec);
return IA64_SPURIOUS_INT_VECTOR;
}
-
VLSAPIC_INSVC(vcpu,vec>>6) |= (1UL <<(vec&63));
- VCPU(vcpu, irr[vec>>6]) &= ~(1UL <<(vec&63));
- if (VCPU(vcpu, vhpi))
- update_vhpi(vcpu, NULL_VECTOR); // clear VHPI till EOI or IRR write
- local_irq_restore(spsr);
+ vmx_vcpu_unpend_interrupt(vcpu, vec);
return (uint64_t)vec;
}
@@ -657,7 +672,6 @@ static void generate_exirq(VCPU *vcpu)
uint64_t isr;
REGS *regs=vcpu_regs(vcpu);
vpsr.val = VCPU(vcpu, vpsr);
- update_vhpi(vcpu, NULL_VECTOR);
isr = vpsr.val & IA64_PSR_RI;
if ( !vpsr.ic )
panic_domain(regs,"Interrupt when IC=0\n");
@@ -669,7 +683,6 @@ void vhpi_detection(VCPU *vcpu)
uint64_t threshold,vhpi;
tpr_t vtpr;
IA64_PSR vpsr;
-
vpsr.val = VCPU(vcpu, vpsr);
vtpr.val = VCPU(vcpu, tpr);
@@ -683,9 +696,5 @@ void vhpi_detection(VCPU *vcpu)
void vmx_vexirq(VCPU *vcpu)
{
- static uint64_t vexirq_count=0;
-
- vexirq_count ++;
- printk("Virtual ex-irq %ld\n", vexirq_count);
generate_exirq (vcpu);
}
diff --git a/xen/arch/ia64/vmx/vmmu.c b/xen/arch/ia64/vmx/vmmu.c
index 9412810f3d..17599de150 100644
--- a/xen/arch/ia64/vmx/vmmu.c
+++ b/xen/arch/ia64/vmx/vmmu.c
@@ -363,7 +363,7 @@ fetch_code(VCPU *vcpu, u64 gip, IA64_BUNDLE *pbundle)
return IA64_NO_FAULT;
}
-IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
+IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, u64 pte, u64 itir, u64 ifa)
{
#ifdef VTLB_DEBUG
int slot;
@@ -382,7 +382,7 @@ IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
return IA64_NO_FAULT;
}
-IA64FAULT vmx_vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
+IA64FAULT vmx_vcpu_itc_d(VCPU *vcpu, u64 pte, u64 itir, u64 ifa)
{
u64 gpfn;
#ifdef VTLB_DEBUG
@@ -456,7 +456,15 @@ IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, u64 slot, u64 pte, u64 itir, u64 ifa)
}
#endif
pte &= ~PAGE_FLAGS_RV_MASK;
- thash_purge_entries(vcpu, va, ps);
+
+ /* This is a bad workaround
+ In Linux, region 7 use 16M pagesize and is identity mapped.
+ VHPT page size is 16K in XEN. If purge VHPT while guest insert 16M,
+ it will iteratively purge VHPT 1024 times, which makes XEN/IPF very
+ slow. XEN doesn't purge VHPT
+ */
+ if (ps != _PAGE_SIZE_16M)
+ thash_purge_entries(vcpu, va, ps);
gpfn = (pte & _PAGE_PPN_MASK)>> PAGE_SHIFT;
if (VMX_DOMAIN(vcpu) && __gpfn_is_io(vcpu->domain, gpfn))
pte |= VTLB_PTE_IO;
@@ -470,7 +478,7 @@ IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, u64 slot, u64 pte, u64 itir, u64 ifa)
-IA64FAULT vmx_vcpu_ptr_d(VCPU *vcpu,UINT64 ifa,UINT64 ps)
+IA64FAULT vmx_vcpu_ptr_d(VCPU *vcpu,u64 ifa, u64 ps)
{
int index;
u64 va;
@@ -483,7 +491,7 @@ IA64FAULT vmx_vcpu_ptr_d(VCPU *vcpu,UINT64 ifa,UINT64 ps)
return IA64_NO_FAULT;
}
-IA64FAULT vmx_vcpu_ptr_i(VCPU *vcpu,UINT64 ifa,UINT64 ps)
+IA64FAULT vmx_vcpu_ptr_i(VCPU *vcpu, u64 ifa, u64 ps)
{
int index;
u64 va;
@@ -496,7 +504,7 @@ IA64FAULT vmx_vcpu_ptr_i(VCPU *vcpu,UINT64 ifa,UINT64 ps)
return IA64_NO_FAULT;
}
-IA64FAULT vmx_vcpu_ptc_l(VCPU *vcpu, UINT64 va, UINT64 ps)
+IA64FAULT vmx_vcpu_ptc_l(VCPU *vcpu, u64 va, u64 ps)
{
va = PAGEALIGN(va, ps);
thash_purge_entries(vcpu, va, ps);
@@ -504,19 +512,19 @@ IA64FAULT vmx_vcpu_ptc_l(VCPU *vcpu, UINT64 va, UINT64 ps)
}
-IA64FAULT vmx_vcpu_ptc_e(VCPU *vcpu, UINT64 va)
+IA64FAULT vmx_vcpu_ptc_e(VCPU *vcpu, u64 va)
{
thash_purge_all(vcpu);
return IA64_NO_FAULT;
}
-IA64FAULT vmx_vcpu_ptc_g(VCPU *vcpu, UINT64 va, UINT64 ps)
+IA64FAULT vmx_vcpu_ptc_g(VCPU *vcpu, u64 va, u64 ps)
{
vmx_vcpu_ptc_ga(vcpu, va, ps);
return IA64_ILLOP_FAULT;
}
/*
-IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu,UINT64 va,UINT64 ps)
+IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu, u64 va, u64 ps)
{
vmx_vcpu_ptc_l(vcpu, va, ps);
return IA64_NO_FAULT;
@@ -554,7 +562,7 @@ static void ptc_ga_remote_func (void *varg)
}
-IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu,UINT64 va,UINT64 ps)
+IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu, u64 va, u64 ps)
{
struct domain *d = vcpu->domain;
@@ -588,7 +596,7 @@ IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu,UINT64 va,UINT64 ps)
}
-IA64FAULT vmx_vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
+IA64FAULT vmx_vcpu_thash(VCPU *vcpu, u64 vadr, u64 *pval)
{
PTA vpta;
ia64_rr vrr;
@@ -608,7 +616,7 @@ IA64FAULT vmx_vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
}
-IA64FAULT vmx_vcpu_ttag(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
+IA64FAULT vmx_vcpu_ttag(VCPU *vcpu, u64 vadr, u64 *pval)
{
ia64_rr vrr;
PTA vpta;
@@ -624,7 +632,7 @@ IA64FAULT vmx_vcpu_ttag(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
-IA64FAULT vmx_vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
+IA64FAULT vmx_vcpu_tpa(VCPU *vcpu, u64 vadr, u64 *padr)
{
thash_data_t *data;
ISR visr,pt_isr;
@@ -637,37 +645,30 @@ IA64FAULT vmx_vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
visr.ei=pt_isr.ei;
visr.ir=pt_isr.ir;
vpsr.val = VCPU(vcpu, vpsr);
- if(vpsr.ic==0){
- visr.ni=1;
- }
visr.na=1;
data = vtlb_lookup(vcpu, vadr, DSIDE_TLB);
if(data){
if(data->p==0){
- visr.na=1;
vcpu_set_isr(vcpu,visr.val);
- page_not_present(vcpu, vadr);
+ data_page_not_present(vcpu, vadr);
return IA64_FAULT;
}else if(data->ma == VA_MATTR_NATPAGE){
- visr.na = 1;
vcpu_set_isr(vcpu, visr.val);
dnat_page_consumption(vcpu, vadr);
return IA64_FAULT;
}else{
*padr = ((data->ppn >> (data->ps - 12)) << data->ps) |
- (vadr & (PSIZE(data->ps) - 1));
+ (vadr & (PSIZE(data->ps) - 1));
return IA64_NO_FAULT;
}
}
data = vhpt_lookup(vadr);
if(data){
if(data->p==0){
- visr.na=1;
vcpu_set_isr(vcpu,visr.val);
- page_not_present(vcpu, vadr);
+ data_page_not_present(vcpu, vadr);
return IA64_FAULT;
}else if(data->ma == VA_MATTR_NATPAGE){
- visr.na = 1;
vcpu_set_isr(vcpu, visr.val);
dnat_page_consumption(vcpu, vadr);
return IA64_FAULT;
@@ -717,7 +718,7 @@ IA64FAULT vmx_vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
}
}
-IA64FAULT vmx_vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key)
+IA64FAULT vmx_vcpu_tak(VCPU *vcpu, u64 vadr, u64 *key)
{
thash_data_t *data;
PTA vpta;
@@ -734,52 +735,3 @@ IA64FAULT vmx_vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key)
}
return IA64_NO_FAULT;
}
-
-/*
- * [FIXME] Is there any effective way to move this routine
- * into vmx_uaccess.h? struct exec_domain is incomplete type
- * in that way...
- *
- * This is the interface to lookup virtual TLB, and then
- * return corresponding machine address in 2nd parameter.
- * The 3rd parameter contains how many bytes mapped by
- * matched vTLB entry, thus to allow caller copy more once.
- *
- * If failed to lookup, -EFAULT is returned. Or else reutrn
- * 0. All upper domain access utilities rely on this routine
- * to determine the real machine address.
- *
- * Yes, put_user and get_user seems to somhow slow upon it.
- * However it's the necessary steps for any vmx domain virtual
- * address, since that's difference address space as HV's one.
- * Later some short-circuit may be created for special case
- */
-long
-__domain_va_to_ma(unsigned long va, unsigned long* ma, unsigned long *len)
-{
- unsigned long mpfn, gpfn, m, n = *len;
- unsigned long end; /* end of the area mapped by current entry */
- thash_data_t *entry;
- struct vcpu *v = current;
-
- entry = vtlb_lookup(v, va, DSIDE_TLB);
- if (entry == NULL)
- return -EFAULT;
-
- gpfn =(entry->ppn>>(PAGE_SHIFT-12));
- gpfn =PAGEALIGN(gpfn,(entry->ps-PAGE_SHIFT));
- gpfn = gpfn | POFFSET(va>>PAGE_SHIFT,(entry->ps-PAGE_SHIFT));
-
- mpfn = gmfn_to_mfn(v->domain, gpfn);
- m = (mpfn<<PAGE_SHIFT) | (va & (PAGE_SIZE - 1));
- /* machine address may be not continuous */
- end = PAGEALIGN(m, PAGE_SHIFT) + PAGE_SIZE;
- /*end = PAGEALIGN(m, entry->ps) + PSIZE(entry->ps);*/
- /* Current entry can't map all requested area */
- if ((m + n) > end)
- n = end - m;
-
- *ma = m;
- *len = n;
- return 0;
-}
diff --git a/xen/arch/ia64/vmx/vmx_entry.S b/xen/arch/ia64/vmx/vmx_entry.S
index 53b00d9019..fa2a53670f 100644
--- a/xen/arch/ia64/vmx/vmx_entry.S
+++ b/xen/arch/ia64/vmx/vmx_entry.S
@@ -669,7 +669,7 @@ GLOBAL_ENTRY(vmx_switch_rr7)
// re-pin mappings for guest_vhpt
- mov r24=IA64_TR_PERVP_VHPT
+ mov r24=IA64_TR_VHPT
movl r25=PAGE_KERNEL
;;
or loc5 = r25,loc5 // construct PA | page properties
diff --git a/xen/arch/ia64/vmx/vmx_init.c b/xen/arch/ia64/vmx/vmx_init.c
index df1bc94de0..2694149d5b 100644
--- a/xen/arch/ia64/vmx/vmx_init.c
+++ b/xen/arch/ia64/vmx/vmx_init.c
@@ -378,7 +378,8 @@ static void vmx_build_physmap_table(struct domain *d)
for (j = io_ranges[i].start;
j < io_ranges[i].start + io_ranges[i].size;
j += PAGE_SIZE)
- __assign_domain_page(d, j, io_ranges[i].type, ASSIGN_writable);
+ (void)__assign_domain_page(d, j, io_ranges[i].type,
+ ASSIGN_writable);
}
/* Map normal memory below 3G */
diff --git a/xen/arch/ia64/vmx/vmx_interrupt.c b/xen/arch/ia64/vmx/vmx_interrupt.c
index c1f6392c41..211aa93b36 100644
--- a/xen/arch/ia64/vmx/vmx_interrupt.c
+++ b/xen/arch/ia64/vmx/vmx_interrupt.c
@@ -383,14 +383,29 @@ dnat_page_consumption (VCPU *vcpu, uint64_t vadr)
/* Deal with
* Page not present vector
*/
-void
-page_not_present(VCPU *vcpu, u64 vadr)
+static void
+__page_not_present(VCPU *vcpu, u64 vadr)
{
/* If vPSR.ic, IFA, ITIR */
set_ifa_itir_iha (vcpu, vadr, 1, 1, 0);
inject_guest_interruption(vcpu, IA64_PAGE_NOT_PRESENT_VECTOR);
}
+
+void
+data_page_not_present(VCPU *vcpu, u64 vadr)
+{
+ __page_not_present(vcpu, vadr);
+}
+
+
+void
+inst_page_not_present(VCPU *vcpu, u64 vadr)
+{
+ __page_not_present(vcpu, vadr);
+}
+
+
/* Deal with
* Data access rights vector
*/
diff --git a/xen/arch/ia64/vmx/vmx_ivt.S b/xen/arch/ia64/vmx/vmx_ivt.S
index 876c942165..625c1b01e5 100644
--- a/xen/arch/ia64/vmx/vmx_ivt.S
+++ b/xen/arch/ia64/vmx/vmx_ivt.S
@@ -772,12 +772,22 @@ ENTRY(vmx_single_step_trap)
VMX_REFLECT(36)
END(vmx_single_step_trap)
+ .global vmx_virtualization_fault_back
.org vmx_ia64_ivt+0x6100
/////////////////////////////////////////////////////////////////////////////////////////
// 0x6100 Entry 37 (size 16 bundles) Virtualization Fault
ENTRY(vmx_virtualization_fault)
// VMX_DBG_FAULT(37)
mov r31=pr
+ ;;
+ cmp.eq p6,p0=EVENT_MOV_FROM_AR,r24
+ cmp.eq p7,p0=EVENT_MOV_FROM_RR,r24
+ cmp.eq p8,p0=EVENT_MOV_TO_RR,r24
+ (p6) br.dptk.many vmx_asm_mov_from_ar
+ (p7) br.dptk.many vmx_asm_mov_from_rr
+ (p8) br.dptk.many vmx_asm_mov_to_rr
+ ;;
+vmx_virtualization_fault_back:
mov r19=37
adds r16 = IA64_VCPU_CAUSE_OFFSET,r21
adds r17 = IA64_VCPU_OPCODE_OFFSET,r21
diff --git a/xen/arch/ia64/vmx/vmx_phy_mode.c b/xen/arch/ia64/vmx/vmx_phy_mode.c
index 8745721d54..d59e74e0e0 100644
--- a/xen/arch/ia64/vmx/vmx_phy_mode.c
+++ b/xen/arch/ia64/vmx/vmx_phy_mode.c
@@ -126,10 +126,16 @@ void
vmx_init_all_rr(VCPU *vcpu)
{
VMX(vcpu, vrr[VRN0]) = 0x38;
+ // enable vhpt in guest physical mode
+ vcpu->arch.metaphysical_rr0 |= 1;
+ vcpu->arch.metaphysical_saved_rr0 = vrrtomrr(vcpu, 0x38);
VMX(vcpu, vrr[VRN1]) = 0x38;
VMX(vcpu, vrr[VRN2]) = 0x38;
VMX(vcpu, vrr[VRN3]) = 0x38;
VMX(vcpu, vrr[VRN4]) = 0x38;
+ // enable vhpt in guest physical mode
+ vcpu->arch.metaphysical_rr4 |= 1;
+ vcpu->arch.metaphysical_saved_rr4 = vrrtomrr(vcpu, 0x38);
VMX(vcpu, vrr[VRN5]) = 0x38;
VMX(vcpu, vrr[VRN6]) = 0x38;
VMX(vcpu, vrr[VRN7]) = 0x738;
@@ -141,11 +147,9 @@ void
vmx_load_all_rr(VCPU *vcpu)
{
unsigned long psr;
- ia64_rr phy_rr;
local_irq_save(psr);
-
/* WARNING: not allow co-exist of both virtual mode and physical
* mode in same region
*/
@@ -154,24 +158,16 @@ vmx_load_all_rr(VCPU *vcpu)
panic_domain(vcpu_regs(vcpu),
"Unexpected domain switch in phy emul\n");
}
- phy_rr.rrval = vcpu->arch.metaphysical_rr0;
- //phy_rr.ps = PAGE_SHIFT;
- phy_rr.ve = 1;
-
- ia64_set_rr((VRN0 << VRN_SHIFT), phy_rr.rrval);
+ ia64_set_rr((VRN0 << VRN_SHIFT), vcpu->arch.metaphysical_rr0);
ia64_dv_serialize_data();
- phy_rr.rrval = vcpu->arch.metaphysical_rr4;
- //phy_rr.ps = PAGE_SHIFT;
- phy_rr.ve = 1;
-
- ia64_set_rr((VRN4 << VRN_SHIFT), phy_rr.rrval);
+ ia64_set_rr((VRN4 << VRN_SHIFT), vcpu->arch.metaphysical_rr4);
ia64_dv_serialize_data();
} else {
ia64_set_rr((VRN0 << VRN_SHIFT),
- vrrtomrr(vcpu, VMX(vcpu, vrr[VRN0])));
+ vcpu->arch.metaphysical_saved_rr0);
ia64_dv_serialize_data();
ia64_set_rr((VRN4 << VRN_SHIFT),
- vrrtomrr(vcpu, VMX(vcpu, vrr[VRN4])));
+ vcpu->arch.metaphysical_saved_rr4);
ia64_dv_serialize_data();
}
@@ -208,22 +204,12 @@ vmx_load_all_rr(VCPU *vcpu)
void
switch_to_physical_rid(VCPU *vcpu)
{
- UINT64 psr;
- ia64_rr phy_rr, mrr;
-
+ u64 psr;
/* Save original virtual mode rr[0] and rr[4] */
psr=ia64_clear_ic();
- phy_rr.rrval = vcpu->domain->arch.metaphysical_rr0;
- mrr.rrval = ia64_get_rr(VRN0 << VRN_SHIFT);
- phy_rr.ps = mrr.ps;
- phy_rr.ve = 1;
- ia64_set_rr(VRN0<<VRN_SHIFT, phy_rr.rrval);
+ ia64_set_rr(VRN0<<VRN_SHIFT, vcpu->arch.metaphysical_rr0);
ia64_srlz_d();
- phy_rr.rrval = vcpu->domain->arch.metaphysical_rr4;
- mrr.rrval = ia64_get_rr(VRN4 << VRN_SHIFT);
- phy_rr.ps = mrr.ps;
- phy_rr.ve = 1;
- ia64_set_rr(VRN4<<VRN_SHIFT, phy_rr.rrval);
+ ia64_set_rr(VRN4<<VRN_SHIFT, vcpu->arch.metaphysical_rr4);
ia64_srlz_d();
ia64_set_psr(psr);
@@ -235,16 +221,11 @@ switch_to_physical_rid(VCPU *vcpu)
void
switch_to_virtual_rid(VCPU *vcpu)
{
- UINT64 psr;
- ia64_rr mrr;
-
+ u64 psr;
psr=ia64_clear_ic();
-
- vcpu_get_rr(vcpu,VRN0<<VRN_SHIFT,&mrr.rrval);
- ia64_set_rr(VRN0<<VRN_SHIFT, vrrtomrr(vcpu, mrr.rrval));
+ ia64_set_rr(VRN0<<VRN_SHIFT, vcpu->arch.metaphysical_saved_rr0);
ia64_srlz_d();
- vcpu_get_rr(vcpu,VRN4<<VRN_SHIFT,&mrr.rrval);
- ia64_set_rr(VRN4<<VRN_SHIFT, vrrtomrr(vcpu, mrr.rrval));
+ ia64_set_rr(VRN4<<VRN_SHIFT, vcpu->arch.metaphysical_saved_rr4);
ia64_srlz_d();
ia64_set_psr(psr);
ia64_srlz_i();
diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c
index 7867fd3993..a0caebfa88 100644
--- a/xen/arch/ia64/vmx/vmx_process.c
+++ b/xen/arch/ia64/vmx/vmx_process.c
@@ -66,7 +66,7 @@ extern unsigned long handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigne
#define DOMN_PAL_REQUEST 0x110000
#define DOMN_SAL_REQUEST 0x110001
-static UINT64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000, 0x1400,0x1800,
+static u64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000,0x1400,0x1800,
0x1c00,0x2000,0x2400,0x2800,0x2c00,0x3000,0x3400,0x3800,0x3c00,0x4000,
0x4400,0x4800,0x4c00,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,
0x5700,0x5800,0x5900,0x5a00,0x5b00,0x5c00,0x5d00,0x5e00,0x5f00,0x6000,
@@ -78,24 +78,35 @@ static UINT64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000, 0x1400,0x1800,
-void vmx_reflect_interruption(UINT64 ifa,UINT64 isr,UINT64 iim,
- UINT64 vector,REGS *regs)
+void vmx_reflect_interruption(u64 ifa, u64 isr, u64 iim,
+ u64 vector, REGS *regs)
{
+ u64 status;
VCPU *vcpu = current;
- UINT64 vpsr = VCPU(vcpu, vpsr);
+ u64 vpsr = VCPU(vcpu, vpsr);
vector=vec2off[vector];
if(!(vpsr&IA64_PSR_IC)&&(vector!=IA64_DATA_NESTED_TLB_VECTOR)){
panic_domain(regs, "Guest nested fault vector=%lx!\n", vector);
}
else{ // handle fpswa emulation
// fp fault
- if(vector == IA64_FP_FAULT_VECTOR && !handle_fpu_swa(1, regs, isr)){
- vmx_vcpu_increment_iip(vcpu);
- return;
+ if (vector == IA64_FP_FAULT_VECTOR) {
+ status = handle_fpu_swa(1, regs, isr);
+ if (!status) {
+ vmx_vcpu_increment_iip(vcpu);
+ return;
+ } else if (IA64_RETRY == status)
+ return;
}
//fp trap
- else if(vector == IA64_FP_TRAP_VECTOR && !handle_fpu_swa(0, regs, isr)){
- return;
+ else if (vector == IA64_FP_TRAP_VECTOR) {
+ status = handle_fpu_swa(0, regs, isr);
+ if (!status)
+ return;
+ else if (IA64_RETRY == status) {
+ vmx_vcpu_decrement_iip(vcpu);
+ return;
+ }
}
}
VCPU(vcpu,isr)=isr;
@@ -187,7 +198,7 @@ void leave_hypervisor_tail(struct pt_regs *regs)
{
struct domain *d = current->domain;
struct vcpu *v = current;
- int callback_irq;
+
// FIXME: Will this work properly if doing an RFI???
if (!is_idle_domain(d) ) { // always comes from guest
// struct pt_regs *user_regs = vcpu_regs(current);
@@ -215,11 +226,14 @@ void leave_hypervisor_tail(struct pt_regs *regs)
// v->arch.irq_new_pending = 1;
// }
- callback_irq = d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
- if (callback_irq != 0 && local_events_need_delivery()) {
- /*inject para-device call back irq*/
- v->vcpu_info->evtchn_upcall_mask = 1;
- vmx_vcpu_pend_interrupt(v, callback_irq);
+ if (v->vcpu_id == 0) {
+ int callback_irq =
+ d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
+ if (callback_irq != 0 && local_events_need_delivery()) {
+ /*inject para-device call back irq*/
+ v->vcpu_info->evtchn_upcall_mask = 1;
+ vmx_vcpu_pend_interrupt(v, callback_irq);
+ }
}
if ( v->arch.irq_new_pending ) {
@@ -228,10 +242,7 @@ void leave_hypervisor_tail(struct pt_regs *regs)
vmx_check_pending_irq(v);
return;
}
- if (VCPU(v, vac).a_int) {
- vhpi_detection(v);
- return;
- }
+
if (v->arch.irq_new_condition) {
v->arch.irq_new_condition = 0;
vhpi_detection(v);
@@ -239,7 +250,7 @@ void leave_hypervisor_tail(struct pt_regs *regs)
}
}
-extern ia64_rr vmx_vcpu_rr(VCPU *vcpu,UINT64 vadr);
+extern ia64_rr vmx_vcpu_rr(VCPU *vcpu, u64 vadr);
static int vmx_handle_lds(REGS* regs)
{
@@ -252,22 +263,27 @@ IA64FAULT
vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
{
IA64_PSR vpsr;
- int type=ISIDE_TLB;
+ int type;
u64 vhpt_adr, gppa, pteval, rr, itir;
ISR misr;
-// REGS *regs;
+ PTA vpta;
thash_data_t *data;
VCPU *v = current;
-#ifdef VTLB_DEBUG
- check_vtlb_sanity(vtlb);
- dump_vtlb(vtlb);
-#endif
+
vpsr.val = VCPU(v, vpsr);
- misr.val=VMX(v,cr_isr);
+ misr.val = VMX(v,cr_isr);
+
+ if (vec == 1)
+ type = ISIDE_TLB;
+ else if (vec == 2)
+ type = DSIDE_TLB;
+ else
+ panic_domain(regs, "wrong vec:%lx\n", vec);
if(is_physical_mode(v)&&(!(vadr<<1>>62))){
if(vec==2){
- if(v->domain!=dom0&&__gpfn_is_io(v->domain,(vadr<<1)>>(PAGE_SHIFT+1))){
+ if (v->domain != dom0
+ && __gpfn_is_io(v->domain, (vadr << 1) >> (PAGE_SHIFT + 1))) {
emulate_io_inst(v,((vadr<<1)>>1),4); // UC
return IA64_FAULT;
}
@@ -275,11 +291,6 @@ vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
physical_tlb_miss(v, vadr);
return IA64_FAULT;
}
- if(vec == 1) type = ISIDE_TLB;
- else if(vec == 2) type = DSIDE_TLB;
- else panic_domain(regs,"wrong vec:%lx\n",vec);
-
-// prepare_if_physical_mode(v);
if((data=vtlb_lookup(v, vadr,type))!=0){
if (v->domain != dom0 && type == DSIDE_TLB) {
@@ -298,95 +309,106 @@ vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
thash_vhpt_insert(v,data->page_flags, data->itir ,vadr);
}else if(type == DSIDE_TLB){
+
if (misr.sp)
return vmx_handle_lds(regs);
+
if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
if(vpsr.ic){
vcpu_set_isr(v, misr.val);
alt_dtlb(v, vadr);
return IA64_FAULT;
} else{
- if(misr.sp){
- //TODO lds emulation
- //panic("Don't support speculation load");
- return vmx_handle_lds(regs);
- }else{
- nested_dtlb(v);
- return IA64_FAULT;
- }
+ nested_dtlb(v);
+ return IA64_FAULT;
}
- } else{
- vmx_vcpu_thash(v, vadr, &vhpt_adr);
- if(!guest_vhpt_lookup(vhpt_adr, &pteval)){
- if ((pteval & _PAGE_P) &&
- ((pteval & _PAGE_MA_MASK) != _PAGE_MA_ST)) {
- vcpu_get_rr(v, vadr, &rr);
- itir = rr&(RR_RID_MASK | RR_PS_MASK);
- thash_purge_and_insert(v, pteval, itir, vadr, DSIDE_TLB);
- return IA64_NO_FAULT;
- }
- if(vpsr.ic){
+ }
+
+ vmx_vcpu_get_pta(v, &vpta.val);
+ if (vpta.vf) {
+ /* Long format is not yet supported. */
+ if (vpsr.ic) {
+ vcpu_set_isr(v, misr.val);
+ dtlb_fault(v, vadr);
+ return IA64_FAULT;
+ } else {
+ nested_dtlb(v);
+ return IA64_FAULT;
+ }
+ }
+
+ vmx_vcpu_thash(v, vadr, &vhpt_adr);
+ if (!guest_vhpt_lookup(vhpt_adr, &pteval)) {
+ /* VHPT successfully read. */
+ if (!(pteval & _PAGE_P)) {
+ if (vpsr.ic) {
vcpu_set_isr(v, misr.val);
- dtlb_fault(v, vadr);
+ data_page_not_present(v, vadr);
return IA64_FAULT;
- }else{
- if(misr.sp){
- //TODO lds emulation
- //panic("Don't support speculation load");
- return vmx_handle_lds(regs);
- }else{
- nested_dtlb(v);
- return IA64_FAULT;
- }
- }
- }else{
- if(vpsr.ic){
- vcpu_set_isr(v, misr.val);
- dvhpt_fault(v, vadr);
+ } else {
+ nested_dtlb(v);
return IA64_FAULT;
- }else{
- if(misr.sp){
- //TODO lds emulation
- //panic("Don't support speculation load");
- return vmx_handle_lds(regs);
- }else{
- nested_dtlb(v);
- return IA64_FAULT;
- }
}
+ } else if ((pteval & _PAGE_MA_MASK) != _PAGE_MA_ST) {
+ vcpu_get_rr(v, vadr, &rr);
+ itir = rr & (RR_RID_MASK | RR_PS_MASK);
+ thash_purge_and_insert(v, pteval, itir, vadr, DSIDE_TLB);
+ return IA64_NO_FAULT;
+ } else if (vpsr.ic) {
+ vcpu_set_isr(v, misr.val);
+ dtlb_fault(v, vadr);
+ return IA64_FAULT;
+ }else{
+ nested_dtlb(v);
+ return IA64_FAULT;
+ }
+ } else {
+ /* Can't read VHPT. */
+ if (vpsr.ic) {
+ vcpu_set_isr(v, misr.val);
+ dvhpt_fault(v, vadr);
+ return IA64_FAULT;
+ } else {
+ nested_dtlb(v);
+ return IA64_FAULT;
}
}
}else if(type == ISIDE_TLB){
+
+ if (!vpsr.ic)
+ misr.ni = 1;
if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){
- if(!vpsr.ic){
- misr.ni=1;
- }
vcpu_set_isr(v, misr.val);
alt_itlb(v, vadr);
return IA64_FAULT;
- } else{
- vmx_vcpu_thash(v, vadr, &vhpt_adr);
- if(!guest_vhpt_lookup(vhpt_adr, &pteval)){
- if (pteval & _PAGE_P){
- vcpu_get_rr(v, vadr, &rr);
- itir = rr&(RR_RID_MASK | RR_PS_MASK);
- thash_purge_and_insert(v, pteval, itir, vadr, ISIDE_TLB);
- return IA64_NO_FAULT;
- }
- if(!vpsr.ic){
- misr.ni=1;
- }
- vcpu_set_isr(v, misr.val);
- itlb_fault(v, vadr);
- return IA64_FAULT;
- }else{
- if(!vpsr.ic){
- misr.ni=1;
- }
+ }
+
+ vmx_vcpu_get_pta(v, &vpta.val);
+ if (vpta.vf) {
+ /* Long format is not yet supported. */
+ vcpu_set_isr(v, misr.val);
+ itlb_fault(v, vadr);
+ return IA64_FAULT;
+ }
+
+
+ vmx_vcpu_thash(v, vadr, &vhpt_adr);
+ if (!guest_vhpt_lookup(vhpt_adr, &pteval)) {
+ /* VHPT successfully read. */
+ if (pteval & _PAGE_P) {
+ vcpu_get_rr(v, vadr, &rr);
+ itir = rr & (RR_RID_MASK | RR_PS_MASK);
+ thash_purge_and_insert(v, pteval, itir, vadr, ISIDE_TLB);
+ return IA64_NO_FAULT;
+ } else {
vcpu_set_isr(v, misr.val);
- ivhpt_fault(v, vadr);
+ inst_page_not_present(v, vadr);
return IA64_FAULT;
}
+ } else {
+ vcpu_set_isr(v, misr.val);
+ ivhpt_fault(v, vadr);
+ return IA64_FAULT;
}
}
return IA64_NO_FAULT;
diff --git a/xen/arch/ia64/vmx/vmx_vcpu.c b/xen/arch/ia64/vmx/vmx_vcpu.c
index e6824d3ec9..3e2583b4fa 100644
--- a/xen/arch/ia64/vmx/vmx_vcpu.c
+++ b/xen/arch/ia64/vmx/vmx_vcpu.c
@@ -82,7 +82,7 @@ void
vmx_vcpu_set_psr(VCPU *vcpu, unsigned long value)
{
- UINT64 mask;
+ u64 mask;
REGS *regs;
IA64_PSR old_psr, new_psr;
old_psr.val=VCPU(vcpu, vpsr);
@@ -172,6 +172,21 @@ IA64FAULT vmx_vcpu_increment_iip(VCPU *vcpu)
}
+IA64FAULT vmx_vcpu_decrement_iip(VCPU *vcpu)
+{
+ REGS *regs = vcpu_regs(vcpu);
+ IA64_PSR *ipsr = (IA64_PSR *)&regs->cr_ipsr;
+
+ if (ipsr->ri == 0) {
+ ipsr->ri = 2;
+ regs->cr_iip -= 16;
+ } else {
+ ipsr->ri--;
+ }
+ return (IA64_NO_FAULT);
+}
+
+
IA64FAULT vmx_vcpu_cover(VCPU *vcpu)
{
REGS *regs = vcpu_regs(vcpu);
@@ -193,23 +208,36 @@ vmx_vcpu_get_plat(VCPU *vcpu)
-IA64FAULT vmx_vcpu_set_rr(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vmx_vcpu_set_rr(VCPU *vcpu, u64 reg, u64 val)
{
ia64_rr oldrr,newrr;
extern void * pal_vaddr;
+ u64 rrval;
vcpu_get_rr(vcpu, reg, &oldrr.rrval);
newrr.rrval=val;
if (newrr.rid >= (1 << vcpu->domain->arch.rid_bits))
panic_domain (NULL, "use of invalid rid %x\n", newrr.rid);
- VMX(vcpu,vrr[reg>>61]) = val;
- switch((u64)(reg>>61)) {
+ VMX(vcpu,vrr[reg>>VRN_SHIFT]) = val;
+ switch((u64)(reg>>VRN_SHIFT)) {
case VRN7:
vmx_switch_rr7(vrrtomrr(vcpu,val),vcpu->domain->shared_info,
(void *)vcpu->arch.privregs,
(void *)vcpu->arch.vhpt.hash, pal_vaddr );
break;
+ case VRN4:
+ rrval = vrrtomrr(vcpu,val);
+ vcpu->arch.metaphysical_saved_rr4 = rrval;
+ if (!is_physical_mode(vcpu))
+ ia64_set_rr(reg,rrval);
+ break;
+ case VRN0:
+ rrval = vrrtomrr(vcpu,val);
+ vcpu->arch.metaphysical_saved_rr0 = rrval;
+ if (!is_physical_mode(vcpu))
+ ia64_set_rr(reg,rrval);
+ break;
default:
ia64_set_rr(reg,vrrtomrr(vcpu,val));
break;
@@ -224,14 +252,14 @@ IA64FAULT vmx_vcpu_set_rr(VCPU *vcpu, UINT64 reg, UINT64 val)
VCPU protection key register access routines
**************************************************************************/
-IA64FAULT vmx_vcpu_get_pkr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vmx_vcpu_get_pkr(VCPU *vcpu, u64 reg, u64 *pval)
{
- UINT64 val = (UINT64)ia64_get_pkr(reg);
+ u64 val = (u64)ia64_get_pkr(reg);
*pval = val;
return (IA64_NO_FAULT);
}
-IA64FAULT vmx_vcpu_set_pkr(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vmx_vcpu_set_pkr(VCPU *vcpu, u64 reg, u64 val)
{
ia64_set_pkr(reg,val);
return (IA64_NO_FAULT);
@@ -267,7 +295,7 @@ u64 vmx_vcpu_get_itir_on_fault(VCPU *vcpu, u64 ifa)
IA64FAULT vmx_vcpu_rfi(VCPU *vcpu)
{
// TODO: Only allowed for current vcpu
- UINT64 ifs, psr;
+ u64 ifs, psr;
REGS *regs = vcpu_regs(vcpu);
psr = VCPU(vcpu,ipsr);
if (psr & IA64_PSR_BN)
@@ -285,7 +313,7 @@ IA64FAULT vmx_vcpu_rfi(VCPU *vcpu)
#if 0
IA64FAULT
-vmx_vcpu_get_bgr(VCPU *vcpu, unsigned int reg, UINT64 *val)
+vmx_vcpu_get_bgr(VCPU *vcpu, unsigned int reg, u64 *val)
{
IA64_PSR vpsr;
@@ -338,7 +366,7 @@ vmx_vcpu_set_bgr(VCPU *vcpu, unsigned int reg, u64 val,int nat)
#endif
#if 0
IA64FAULT
-vmx_vcpu_get_gr(VCPU *vcpu, unsigned reg, UINT64 * val)
+vmx_vcpu_get_gr(VCPU *vcpu, unsigned reg, u64 * val)
{
REGS *regs=vcpu_regs(vcpu);
int nat;
@@ -385,18 +413,18 @@ vmx_vcpu_set_gr(VCPU *vcpu, unsigned reg, u64 value, int nat)
This function gets guest PSR
*/
-UINT64 vmx_vcpu_get_psr(VCPU *vcpu)
+u64 vmx_vcpu_get_psr(VCPU *vcpu)
{
- UINT64 mask;
+ u64 mask;
REGS *regs = vcpu_regs(vcpu);
mask = IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL |
IA64_PSR_MFH | IA64_PSR_CPL | IA64_PSR_RI;
return (VCPU(vcpu, vpsr) & ~mask) | (regs->cr_ipsr & mask);
}
-IA64FAULT vmx_vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
+IA64FAULT vmx_vcpu_reset_psr_sm(VCPU *vcpu, u64 imm24)
{
- UINT64 vpsr;
+ u64 vpsr;
vpsr = vmx_vcpu_get_psr(vcpu);
vpsr &= (~imm24);
vmx_vcpu_set_psr(vcpu, vpsr);
@@ -404,9 +432,9 @@ IA64FAULT vmx_vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
}
-IA64FAULT vmx_vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
+IA64FAULT vmx_vcpu_set_psr_sm(VCPU *vcpu, u64 imm24)
{
- UINT64 vpsr;
+ u64 vpsr;
vpsr = vmx_vcpu_get_psr(vcpu);
vpsr |= imm24;
vmx_vcpu_set_psr(vcpu, vpsr);
@@ -414,7 +442,7 @@ IA64FAULT vmx_vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
}
-IA64FAULT vmx_vcpu_set_psr_l(VCPU *vcpu, UINT64 val)
+IA64FAULT vmx_vcpu_set_psr_l(VCPU *vcpu, u64 val)
{
val = (val & MASK(0, 32)) | (vmx_vcpu_get_psr(vcpu) & MASK(32, 32));
vmx_vcpu_set_psr(vcpu, val);
diff --git a/xen/arch/ia64/vmx/vmx_virt.c b/xen/arch/ia64/vmx/vmx_virt.c
index 6fcb37090a..5c719309ea 100644
--- a/xen/arch/ia64/vmx/vmx_virt.c
+++ b/xen/arch/ia64/vmx/vmx_virt.c
@@ -32,7 +32,7 @@
#include <asm/vmx_phy_mode.h>
void
-ia64_priv_decoder(IA64_SLOT_TYPE slot_type, INST64 inst, UINT64 * cause)
+ia64_priv_decoder(IA64_SLOT_TYPE slot_type, INST64 inst, u64 * cause)
{
*cause=0;
switch (slot_type) {
@@ -144,20 +144,20 @@ ia64_priv_decoder(IA64_SLOT_TYPE slot_type, INST64 inst, UINT64 * cause)
IA64FAULT vmx_emul_rsm(VCPU *vcpu, INST64 inst)
{
- UINT64 imm24 = (inst.M44.i<<23)|(inst.M44.i2<<21)|inst.M44.imm;
+ u64 imm24 = (inst.M44.i << 23) | (inst.M44.i2 << 21) | inst.M44.imm;
return vmx_vcpu_reset_psr_sm(vcpu,imm24);
}
IA64FAULT vmx_emul_ssm(VCPU *vcpu, INST64 inst)
{
- UINT64 imm24 = (inst.M44.i<<23)|(inst.M44.i2<<21)|inst.M44.imm;
+ u64 imm24 = (inst.M44.i << 23) | (inst.M44.i2 << 21) | inst.M44.imm;
return vmx_vcpu_set_psr_sm(vcpu,imm24);
}
IA64FAULT vmx_emul_mov_from_psr(VCPU *vcpu, INST64 inst)
{
- UINT64 tgt = inst.M33.r1;
- UINT64 val;
+ u64 tgt = inst.M33.r1;
+ u64 val;
/*
if ((fault = vmx_vcpu_get_psr(vcpu,&val)) == IA64_NO_FAULT)
@@ -174,7 +174,7 @@ IA64FAULT vmx_emul_mov_from_psr(VCPU *vcpu, INST64 inst)
*/
IA64FAULT vmx_emul_mov_to_psr(VCPU *vcpu, INST64 inst)
{
- UINT64 val;
+ u64 val;
if(vcpu_get_gr_nat(vcpu, inst.M35.r2, &val) != IA64_NO_FAULT)
panic_domain(vcpu_regs(vcpu),"get_psr nat bit fault\n");
@@ -566,7 +566,7 @@ IA64FAULT vmx_emul_tak(VCPU *vcpu, INST64 inst)
IA64FAULT vmx_emul_itr_d(VCPU *vcpu, INST64 inst)
{
- UINT64 itir, ifa, pte, slot;
+ u64 itir, ifa, pte, slot;
#ifdef VMAL_NO_FAULT_CHECK
IA64_PSR vpsr;
vpsr.val=vmx_vcpu_get_psr(vcpu);
@@ -623,7 +623,7 @@ IA64FAULT vmx_emul_itr_d(VCPU *vcpu, INST64 inst)
IA64FAULT vmx_emul_itr_i(VCPU *vcpu, INST64 inst)
{
- UINT64 itir, ifa, pte, slot;
+ u64 itir, ifa, pte, slot;
#ifdef VMAL_NO_FAULT_CHECK
ISR isr;
IA64_PSR vpsr;
@@ -691,7 +691,7 @@ IA64FAULT itc_fault_check(VCPU *vcpu, INST64 inst, u64 *itir, u64 *ifa,u64 *pte)
return IA64_FAULT;
}
- UINT64 fault;
+ u64 fault;
ISR isr;
if ( vpsr.cpl != 0) {
/* Inject Privileged Operation fault into guest */
@@ -729,7 +729,7 @@ IA64FAULT itc_fault_check(VCPU *vcpu, INST64 inst, u64 *itir, u64 *ifa,u64 *pte)
IA64FAULT vmx_emul_itc_d(VCPU *vcpu, INST64 inst)
{
- UINT64 itir, ifa, pte;
+ u64 itir, ifa, pte;
if ( itc_fault_check(vcpu, inst, &itir, &ifa, &pte) == IA64_FAULT ) {
return IA64_FAULT;
@@ -740,7 +740,7 @@ IA64FAULT vmx_emul_itc_d(VCPU *vcpu, INST64 inst)
IA64FAULT vmx_emul_itc_i(VCPU *vcpu, INST64 inst)
{
- UINT64 itir, ifa, pte;
+ u64 itir, ifa, pte;
if ( itc_fault_check(vcpu, inst, &itir, &ifa, &pte) == IA64_FAULT ) {
return IA64_FAULT;
@@ -757,7 +757,7 @@ IA64FAULT vmx_emul_itc_i(VCPU *vcpu, INST64 inst)
IA64FAULT vmx_emul_mov_to_ar_imm(VCPU *vcpu, INST64 inst)
{
// I27 and M30 are identical for these fields
- UINT64 imm;
+ u64 imm;
if(inst.M30.ar3!=44){
panic_domain(vcpu_regs(vcpu),"Can't support ar register other than itc");
@@ -1277,8 +1277,8 @@ IA64FAULT vmx_emul_mov_to_cr(VCPU *vcpu, INST64 inst)
IA64FAULT vmx_emul_mov_from_cr(VCPU *vcpu, INST64 inst)
{
- UINT64 tgt = inst.M33.r1;
- UINT64 val;
+ u64 tgt = inst.M33.r1;
+ u64 val;
IA64FAULT fault;
#ifdef CHECK_FAULT
IA64_PSR vpsr;
@@ -1353,7 +1353,7 @@ vmx_emulate(VCPU *vcpu, REGS *regs)
{
IA64FAULT status;
INST64 inst;
- UINT64 iip, cause, opcode;
+ u64 iip, cause, opcode;
iip = regs->cr_iip;
cause = VMX(vcpu,cause);
opcode = VMX(vcpu,opcode);
diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c
index 4fb31a0ec2..2e83358972 100644
--- a/xen/arch/ia64/vmx/vtlb.c
+++ b/xen/arch/ia64/vmx/vtlb.c
@@ -218,7 +218,6 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
{
u64 ret;
thash_data_t * data;
- PTA vpta;
data = vhpt_lookup(iha);
if (data == NULL) {
@@ -227,13 +226,6 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte)
thash_vhpt_insert(current, data->page_flags, data->itir ,iha);
}
- /* VHPT long format is not read. */
- vmx_vcpu_get_pta(current, &vpta.val);
- if (vpta.vf == 1) {
- *pte = 0;
- return 0;
- }
-
asm volatile ("rsm psr.ic|psr.i;;"
"srlz.d;;"
"ld8.s r9=[%1];;"
diff --git a/xen/arch/ia64/xen/Makefile b/xen/arch/ia64/xen/Makefile
index b51029f043..87f22f0966 100644
--- a/xen/arch/ia64/xen/Makefile
+++ b/xen/arch/ia64/xen/Makefile
@@ -25,5 +25,9 @@ obj-y += xensetup.o
obj-y += xentime.o
obj-y += flushd.o
obj-y += privop_stat.o
+obj-y += xenpatch.o
+obj-y += xencomm.o
obj-$(crash_debug) += gdbstub.o
+obj-$(xen_ia64_tlb_track) += tlb_track.o
+obj-$(xen_ia64_tlbflush_clock) += flushtlb.o
diff --git a/xen/arch/ia64/xen/dom0_ops.c b/xen/arch/ia64/xen/dom0_ops.c
index 8bb24010ce..341d66b7bf 100644
--- a/xen/arch/ia64/xen/dom0_ops.c
+++ b/xen/arch/ia64/xen/dom0_ops.c
@@ -256,6 +256,7 @@ do_dom0vp_op(unsigned long cmd,
} else {
ret = (ret & _PFN_MASK) >> PAGE_SHIFT;//XXX pte_pfn()
}
+ perfc_incrc(dom0vp_phystomach);
break;
case IA64_DOM0VP_machtophys:
if (!mfn_valid(arg0)) {
@@ -263,6 +264,7 @@ do_dom0vp_op(unsigned long cmd,
break;
}
ret = get_gpfn_from_mfn(arg0);
+ perfc_incrc(dom0vp_machtophys);
break;
case IA64_DOM0VP_zap_physmap:
ret = dom0vp_zap_physmap(d, arg0, (unsigned int)arg1);
@@ -271,6 +273,9 @@ do_dom0vp_op(unsigned long cmd,
ret = dom0vp_add_physmap(d, arg0, arg1, (unsigned int)arg2,
(domid_t)arg3);
break;
+ case IA64_DOM0VP_expose_p2m:
+ ret = dom0vp_expose_p2m(d, arg0, arg1, arg2, arg3);
+ break;
default:
ret = -1;
printf("unknown dom0_vp_op 0x%lx\n", cmd);
diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c
index 2073fd52c7..13d0cab731 100644
--- a/xen/arch/ia64/xen/domain.c
+++ b/xen/arch/ia64/xen/domain.c
@@ -46,9 +46,10 @@
#include <asm/regionreg.h>
#include <asm/dom_fw.h>
#include <asm/shadow.h>
+#include <xen/guest_access.h>
+#include <asm/tlb_track.h>
unsigned long dom0_size = 512*1024*1024;
-unsigned long dom0_align = 64*1024*1024;
/* dom0_max_vcpus: maximum number of VCPUs to create for dom0. */
static unsigned int dom0_max_vcpus = 1;
@@ -58,13 +59,8 @@ extern unsigned long running_on_sim;
extern char dom0_command_line[];
-/* FIXME: where these declarations should be there ? */
-extern void serial_input_init(void);
+/* forward declaration */
static void init_switch_stack(struct vcpu *v);
-extern void vmx_do_launch(struct vcpu *);
-
-/* this belongs in include/asm, but there doesn't seem to be a suitable place */
-extern struct vcpu *ia64_switch_to (struct vcpu *next_task);
/* Address of vpsr.i (in fact evtchn_upcall_mask) of current vcpu.
This is a Xen virtual address. */
@@ -73,33 +69,68 @@ DEFINE_PER_CPU(int *, current_psr_ic_addr);
#include <xen/sched-if.h>
-static void flush_vtlb_for_context_switch(struct vcpu* vcpu)
+static void
+ia64_disable_vhpt_walker(void)
+{
+ // disable VHPT. ia64_new_rr7() might cause VHPT
+ // fault without this because it flushes dtr[IA64_TR_VHPT]
+ // (VHPT_SIZE_LOG2 << 2) is just for avoid
+ // Reserved Register/Field fault.
+ ia64_set_pta(VHPT_SIZE_LOG2 << 2);
+}
+
+static void flush_vtlb_for_context_switch(struct vcpu* prev, struct vcpu* next)
{
int cpu = smp_processor_id();
- int last_vcpu_id = vcpu->domain->arch.last_vcpu[cpu].vcpu_id;
- int last_processor = vcpu->arch.last_processor;
+ int last_vcpu_id, last_processor;
- if (is_idle_domain(vcpu->domain))
+ if (!is_idle_domain(prev->domain))
+ tlbflush_update_time
+ (&prev->domain->arch.last_vcpu[cpu].tlbflush_timestamp,
+ tlbflush_current_time());
+
+ if (is_idle_domain(next->domain))
return;
-
- vcpu->domain->arch.last_vcpu[cpu].vcpu_id = vcpu->vcpu_id;
- vcpu->arch.last_processor = cpu;
- if ((last_vcpu_id != vcpu->vcpu_id &&
+ last_vcpu_id = next->domain->arch.last_vcpu[cpu].vcpu_id;
+ last_processor = next->arch.last_processor;
+
+ next->domain->arch.last_vcpu[cpu].vcpu_id = next->vcpu_id;
+ next->arch.last_processor = cpu;
+
+ if ((last_vcpu_id != next->vcpu_id &&
last_vcpu_id != INVALID_VCPU_ID) ||
- (last_vcpu_id == vcpu->vcpu_id &&
+ (last_vcpu_id == next->vcpu_id &&
last_processor != cpu &&
last_processor != INVALID_PROCESSOR)) {
+#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
+ u32 last_tlbflush_timestamp =
+ next->domain->arch.last_vcpu[cpu].tlbflush_timestamp;
+#endif
+ int vhpt_is_flushed = 0;
// if the vTLB implementation was changed,
// the followings must be updated either.
- if (VMX_DOMAIN(vcpu)) {
+ if (VMX_DOMAIN(next)) {
// currently vTLB for vt-i domian is per vcpu.
// so any flushing isn't needed.
+ } else if (HAS_PERVCPU_VHPT(next->domain)) {
+ // nothing to do
+ } else {
+ if (NEED_FLUSH(__get_cpu_var(vhpt_tlbflush_timestamp),
+ last_tlbflush_timestamp)) {
+ local_vhpt_flush();
+ vhpt_is_flushed = 1;
+ }
+ }
+ if (vhpt_is_flushed || NEED_FLUSH(__get_cpu_var(tlbflush_time),
+ last_tlbflush_timestamp)) {
+ local_flush_tlb_all();
+ perfc_incrc(tlbflush_clock_cswitch_purge);
} else {
- vhpt_flush();
+ perfc_incrc(tlbflush_clock_cswitch_skip);
}
- local_flush_tlb_all();
+ perfc_incrc(flush_vtlb_for_context_switch);
}
}
@@ -108,15 +139,15 @@ void schedule_tail(struct vcpu *prev)
extern char ia64_ivt;
context_saved(prev);
+ ia64_disable_vhpt_walker();
if (VMX_DOMAIN(current)) {
vmx_do_launch(current);
migrate_timer(&current->arch.arch_vmx.vtm.vtm_timer,
current->processor);
} else {
ia64_set_iva(&ia64_ivt);
- ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
- VHPT_ENABLED);
load_region_regs(current);
+ ia64_set_pta(vcpu_pta(current));
vcpu_load_kernel_regs(current);
__ia64_per_cpu_var(current_psr_i_addr) = &current->domain->
shared_info->vcpu_info[current->vcpu_id].evtchn_upcall_mask;
@@ -124,13 +155,12 @@ void schedule_tail(struct vcpu *prev)
(current->domain->arch.shared_info_va + XSI_PSR_IC_OFS);
migrate_timer(&current->arch.hlt_timer, current->processor);
}
- flush_vtlb_for_context_switch(current);
+ flush_vtlb_for_context_switch(prev, current);
}
void context_switch(struct vcpu *prev, struct vcpu *next)
{
uint64_t spsr;
- uint64_t pta;
local_irq_save(spsr);
@@ -148,6 +178,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
}
if (VMX_DOMAIN(next))
vmx_load_state(next);
+
+ ia64_disable_vhpt_walker();
/*ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next);*/
prev = ia64_switch_to(next);
@@ -167,9 +199,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
nd = current->domain;
if (!is_idle_domain(nd)) {
- ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
- VHPT_ENABLED);
load_region_regs(current);
+ ia64_set_pta(vcpu_pta(current));
vcpu_load_kernel_regs(current);
vcpu_set_next_timer(current);
if (vcpu_timer_expired(current))
@@ -183,14 +214,12 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
* walker. Then all accesses happen within idle context will
* be handled by TR mapping and identity mapping.
*/
- pta = ia64_get_pta();
- ia64_set_pta(pta & ~VHPT_ENABLED);
__ia64_per_cpu_var(current_psr_i_addr) = NULL;
__ia64_per_cpu_var(current_psr_ic_addr) = NULL;
}
}
- flush_vtlb_for_context_switch(current);
local_irq_restore(spsr);
+ flush_vtlb_for_context_switch(prev, current);
context_saved(prev);
}
@@ -273,6 +302,13 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
if (!d->arch.is_vti) {
int order;
int i;
+ // vti domain has its own vhpt policy.
+ if (HAS_PERVCPU_VHPT(d)) {
+ if (pervcpu_vhpt_alloc(v) < 0) {
+ free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
+ return NULL;
+ }
+ }
/* Create privregs page only if not VTi. */
order = get_order_from_shift(XMAPPEDREGS_SHIFT);
@@ -282,6 +318,9 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
for (i = 0; i < (1 << order); i++)
share_xen_page_with_guest(virt_to_page(v->arch.privregs) +
i, d, XENSHARE_writable);
+
+ tlbflush_update_time(&v->arch.tlbflush_timestamp,
+ tlbflush_current_time());
}
v->arch.metaphysical_rr0 = d->arch.metaphysical_rr0;
@@ -315,6 +354,8 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
void relinquish_vcpu_resources(struct vcpu *v)
{
+ if (HAS_PERVCPU_VHPT(v->domain))
+ pervcpu_vhpt_free(v);
if (v->arch.privregs != NULL) {
free_xenheap_pages(v->arch.privregs,
get_order_from_shift(XMAPPEDREGS_SHIFT));
@@ -325,7 +366,7 @@ void relinquish_vcpu_resources(struct vcpu *v)
void free_vcpu_struct(struct vcpu *v)
{
- if (VMX_DOMAIN(v))
+ if (v->domain->arch.is_vti)
vmx_relinquish_vcpu_resources(v);
else
relinquish_vcpu_resources(v);
@@ -350,6 +391,11 @@ static void init_switch_stack(struct vcpu *v)
memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
}
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+static int opt_pervcpu_vhpt = 1;
+integer_param("pervcpu_vhpt", opt_pervcpu_vhpt);
+#endif
+
int arch_domain_create(struct domain *d)
{
int i;
@@ -364,6 +410,13 @@ int arch_domain_create(struct domain *d)
if (is_idle_domain(d))
return 0;
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+ d->arch.has_pervcpu_vhpt = opt_pervcpu_vhpt;
+ DPRINTK("%s:%d domain %d pervcpu_vhpt %d\n",
+ __func__, __LINE__, d->domain_id, d->arch.has_pervcpu_vhpt);
+#endif
+ if (tlb_track_create(d) < 0)
+ goto fail_nomem1;
d->shared_info = alloc_xenheap_pages(get_order_from_shift(XSI_SHIFT));
if (d->shared_info == NULL)
goto fail_nomem;
@@ -392,6 +445,8 @@ int arch_domain_create(struct domain *d)
return 0;
fail_nomem:
+ tlb_track_destroy(d);
+fail_nomem1:
if (d->arch.mm.pgd != NULL)
pgd_free(d->arch.mm.pgd);
if (d->shared_info != NULL)
@@ -407,6 +462,8 @@ void arch_domain_destroy(struct domain *d)
if (d->arch.shadow_bitmap != NULL)
xfree(d->arch.shadow_bitmap);
+ tlb_track_destroy(d);
+
/* Clear vTLB for the next domain. */
domain_flush_tlb_vhpt(d);
@@ -844,23 +901,6 @@ void alloc_dom0(void)
" (try e.g. dom0_mem=256M or dom0_mem=65536K)\n");
}
- /* Check dom0 align. */
- if ((dom0_align - 1) & dom0_align) { /* not a power of two */
- panic("dom0_align (%lx) must be power of two, boot aborted"
- " (try e.g. dom0_align=256M or dom0_align=65536K)\n",
- dom0_align);
- }
- if (dom0_align < PAGE_SIZE) {
- panic("dom0_align must be >= %ld, boot aborted"
- " (try e.g. dom0_align=256M or dom0_align=65536K)\n",
- PAGE_SIZE);
- }
- if (dom0_size % dom0_align) {
- dom0_size = (dom0_size / dom0_align + 1) * dom0_align;
- printf("dom0_size rounded up to %ld, due to dom0_align=%lx\n",
- dom0_size,dom0_align);
- }
-
if (running_on_sim) {
dom0_size = 128*1024*1024; //FIXME: Should be configurable
}
@@ -1101,9 +1141,6 @@ int construct_dom0(struct domain *d,
physdev_init_dom0(d);
- // FIXME: Hack for keyboard input
- //serial_input_init();
-
return 0;
}
@@ -1142,10 +1179,3 @@ static void parse_dom0_mem(char *s)
dom0_size = parse_size_and_unit(s);
}
custom_param("dom0_mem", parse_dom0_mem);
-
-
-static void parse_dom0_align(char *s)
-{
- dom0_align = parse_size_and_unit(s);
-}
-custom_param("dom0_align", parse_dom0_align);
diff --git a/xen/arch/ia64/xen/faults.c b/xen/arch/ia64/xen/faults.c
index f2e3a1bef7..75be0088e7 100644
--- a/xen/arch/ia64/xen/faults.c
+++ b/xen/arch/ia64/xen/faults.c
@@ -31,6 +31,7 @@
#include <asm/asm-xsi-offsets.h>
#include <asm/shadow.h>
#include <asm/uaccess.h>
+#include <asm/p2m_entry.h>
extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
/* FIXME: where these declarations shold be there ? */
@@ -202,8 +203,11 @@ void ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_reg
fault = vcpu_translate(current,address,is_data,&pteval,&itir,&iha);
if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
struct p2m_entry entry;
- pteval = translate_domain_pte(pteval, address, itir, &logps, &entry);
- vcpu_itc_no_srlz(current,is_data?2:1,address,pteval,-1UL,logps);
+ unsigned long m_pteval;
+ m_pteval = translate_domain_pte(pteval, address, itir,
+ &logps, &entry);
+ vcpu_itc_no_srlz(current, (is_data? 2: 1) | 4,
+ address, m_pteval, pteval, logps, &entry);
if ((fault == IA64_USE_TLB && !current->arch.dtlb.pte.p) ||
p2m_entry_retry(&entry)) {
/* dtlb has been purged in-between. This dtlb was
@@ -228,10 +232,10 @@ void ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_reg
// indicate a bad xen pointer
printk("*** xen_handle_domain_access: exception table"
" lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
- iip, address);
+ iip, address);
panic_domain(regs,"*** xen_handle_domain_access: exception table"
- " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
- iip, address);
+ " lookup failed, iip=0x%lx, addr=0x%lx, spinning...\n",
+ iip, address);
}
return;
}
diff --git a/xen/arch/ia64/xen/flushtlb.c b/xen/arch/ia64/xen/flushtlb.c
new file mode 100644
index 0000000000..0c77c1b6df
--- /dev/null
+++ b/xen/arch/ia64/xen/flushtlb.c
@@ -0,0 +1,117 @@
+/******************************************************************************
+ * flushtlb.c
+ * based on x86 flushtlb.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 <xen/sched.h>
+#include <xen/softirq.h>
+#include <asm/vcpu.h>
+#include <asm/vhpt.h>
+#include <asm/flushtlb.h>
+
+/* Debug builds: Wrap frequently to stress-test the wrap logic. */
+#ifdef NDEBUG
+#define WRAP_MASK (0xFFFFFFFFU)
+#else
+#define WRAP_MASK (0x000003FFU)
+#endif
+
+volatile u32 tlbflush_clock = 1U; /* 1 greater than tlbflush_time. */
+DEFINE_PER_CPU(volatile u32, tlbflush_time);
+
+u32
+tlbflush_clock_inc_and_return(void)
+{
+ u32 t, t1, t2;
+
+ t = tlbflush_clock;
+ do {
+ t1 = t2 = t;
+ /* Clock wrapped: someone else is leading a global TLB shootdown. */
+ if (unlikely(t1 == 0))
+ return t2;
+ t2 = (t + 1) & WRAP_MASK;
+ t = ia64_cmpxchg(acq, &tlbflush_clock, t1, t2, sizeof(tlbflush_clock));
+ } while (unlikely(t != t1));
+
+ /* Clock wrapped: we will lead a global TLB shootdown. */
+ if (unlikely(t2 == 0))
+ raise_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ);
+
+ return t2;
+}
+
+void
+new_tlbflush_clock_period(void)
+{
+ /*
+ *XXX TODO
+ * If flushing all vcpu's vhpt takes too long, it can be done backgroundly.
+ * In such case tlbflush time comparison is done using only 31bit
+ * similar to linux jiffies comparison.
+ * vhpt should be flushed gradually before wraping 31bits.
+ *
+ * Sample calculation.
+ * Currently Xen/IA64 can create up to 64 domains at the same time.
+ * Vhpt size is currently 64KB. (This might be changed later though)
+ * Suppose each domains have 4 vcpus (or 16 vcpus).
+ * then the memory size which must be flushed is 16MB (64MB).
+ */
+ struct domain* d;
+ struct vcpu* v;
+ /* flush all vhpt of vcpu of all existing domain. */
+ read_lock(&domlist_lock);
+ for_each_domain(d) {
+ for_each_vcpu(d, v) {
+ vcpu_purge_tr_entry(&PSCBX(v,dtlb));
+ vcpu_purge_tr_entry(&PSCBX(v,itlb));
+ }
+ }
+ smp_mb();
+ for_each_domain(d) {
+ for_each_vcpu(d, v) {
+ if (HAS_PERVCPU_VHPT(v->domain))
+ vcpu_vhpt_flush(v);
+ }
+ }
+ read_unlock(&domlist_lock);
+ /* unlock has release semantics */
+
+ /* flush all vhpt of physical cpu and mTLB */
+ on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1);
+
+ /*
+ * if global TLB shootdown is finished, increment tlbflush_time
+ * atomic operation isn't necessary because we know that tlbflush_clock
+ * stays 0.
+ */
+ tlbflush_clock++;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/ia64/xen/fw_emul.c b/xen/arch/ia64/xen/fw_emul.c
index 77f1b288da..2c4af786e3 100644
--- a/xen/arch/ia64/xen/fw_emul.c
+++ b/xen/arch/ia64/xen/fw_emul.c
@@ -16,7 +16,6 @@
*
*/
#include <xen/config.h>
-#include <xen/console.h>
#include <asm/system.h>
#include <asm/pgalloc.h>
@@ -27,8 +26,11 @@
#include <public/sched.h>
#include "hpsim_ssc.h"
#include <asm/vcpu.h>
+#include <asm/vmx_vcpu.h>
#include <asm/dom_fw.h>
#include <asm/uaccess.h>
+#include <xen/console.h>
+#include <xen/hypercall.h>
extern unsigned long running_on_sim;
@@ -173,6 +175,10 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
break;
case PAL_FREQ_BASE:
status = ia64_pal_freq_base(&r9);
+ if (status == PAL_STATUS_UNIMPLEMENTED) {
+ status = ia64_sal_freq_base(0, &r9, &r10);
+ r10 = 0;
+ }
break;
case PAL_PROC_GET_FEATURES:
status = ia64_pal_proc_get_features(&r9,&r10,&r11);
@@ -215,7 +221,7 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
{
/* Use xen-specific values.
hash_tag_id is somewhat random! */
- const pal_vm_info_1_u_t v1 =
+ static const pal_vm_info_1_u_t v1 =
{.pal_vm_info_1_s =
{ .vw = 1,
.phys_add_size = 44,
@@ -232,11 +238,12 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
.num_tc_levels = 1
#endif
}};
- const pal_vm_info_2_u_t v2 =
- { .pal_vm_info_2_s =
- { .impl_va_msb = 50,
- .rid_size = current->domain->arch.rid_bits,
- .reserved = 0 }};
+ pal_vm_info_2_u_t v2;
+ v2.pvi2_val = 0;
+ v2.pal_vm_info_2_s.rid_size =
+ current->domain->arch.rid_bits;
+ v2.pal_vm_info_2_s.impl_va_msb =
+ VMX_DOMAIN(current) ? GUEST_IMPL_VA_MSB : 50;
r9 = v1.pvi1_val;
r10 = v2.pvi2_val;
status = PAL_STATUS_SUCCESS;
@@ -294,9 +301,20 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
status = ia64_pal_register_info(in1, &r9, &r10);
break;
case PAL_CACHE_FLUSH:
- /* FIXME */
- printk("PAL_CACHE_FLUSH NOT IMPLEMENTED!\n");
- BUG();
+ /* Always call Host Pal in int=0 */
+ in2 &= ~PAL_CACHE_FLUSH_CHK_INTRS;
+
+ /*
+ * Call Host PAL cache flush
+ * Clear psr.ic when call PAL_CACHE_FLUSH
+ */
+ r10 = in3;
+ status = ia64_pal_cache_flush(in1, in2, &r10, &r9);
+
+ if (status != 0)
+ panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
+ "status %lx", status);
+
break;
case PAL_PERF_MON_INFO:
{
@@ -343,15 +361,26 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
}
break;
case PAL_HALT:
- if (current->domain == dom0) {
- printf ("Domain0 halts the machine\n");
- console_start_sync();
- (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL);
- }
- else
- domain_shutdown (current->domain,
- SHUTDOWN_poweroff);
- break;
+ if (current->domain == dom0) {
+ printf ("Domain0 halts the machine\n");
+ console_start_sync();
+ (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL);
+ }
+ else
+ domain_shutdown(current->domain, SHUTDOWN_poweroff);
+ break;
+ case PAL_HALT_LIGHT:
+ if (VMX_DOMAIN(current)) {
+ /* Called by VTI. */
+ if (!is_unmasked_irq(current))
+ do_sched_op_compat(SCHEDOP_block, 0);
+ status = PAL_STATUS_SUCCESS;
+ }
+ break;
+ case PAL_PLATFORM_ADDR:
+ if (VMX_DOMAIN(current))
+ status = PAL_STATUS_SUCCESS;
+ break;
default:
printk("xen_pal_emulator: UNIMPLEMENTED PAL CALL %lu!!!!\n",
index);
diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c
index 17ad53bd71..8fc4c4c3cb 100644
--- a/xen/arch/ia64/xen/hypercall.c
+++ b/xen/arch/ia64/xen/hypercall.c
@@ -32,7 +32,6 @@
#include <xen/event.h>
#include <xen/perfc.h>
-static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop);
static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg);
static long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg);
@@ -54,10 +53,10 @@ const hypercall_t ia64_hypercall_table[NR_hypercalls] =
(hypercall_t)do_multicall,
(hypercall_t)do_ni_hypercall, /* do_update_va_mapping */
(hypercall_t)do_ni_hypercall, /* do_set_timer_op */ /* 15 */
- (hypercall_t)do_event_channel_op_compat,
+ (hypercall_t)do_ni_hypercall,
(hypercall_t)do_xen_version,
(hypercall_t)do_console_io,
- (hypercall_t)do_physdev_op_compat,
+ (hypercall_t)do_ni_hypercall,
(hypercall_t)do_grant_table_op, /* 20 */
(hypercall_t)do_ni_hypercall, /* do_vm_assist */
(hypercall_t)do_ni_hypercall, /* do_update_va_mapping_othe */
@@ -108,19 +107,6 @@ static IA64FAULT
xen_hypercall (struct pt_regs *regs)
{
uint32_t cmd = (uint32_t)regs->r2;
- struct vcpu *v = current;
-
- if (cmd == __HYPERVISOR_grant_table_op) {
- XEN_GUEST_HANDLE(void) uop;
-
- v->arch.hypercall_param.va = regs->r15;
- v->arch.hypercall_param.pa1 = regs->r17;
- v->arch.hypercall_param.pa2 = regs->r18;
- set_xen_guest_handle(uop, (void *)regs->r15);
- regs->r8 = do_grant_table_op(regs->r14, uop, regs->r16);
- v->arch.hypercall_param.va = 0;
- return IA64_NO_FAULT;
- }
if (cmd < NR_hypercalls) {
perfc_incra(hypercalls, cmd);
@@ -133,7 +119,21 @@ xen_hypercall (struct pt_regs *regs)
regs->r19);
} else
regs->r8 = -ENOSYS;
+
+ return IA64_NO_FAULT;
+}
+static IA64FAULT
+xen_fast_hypercall (struct pt_regs *regs)
+{
+ uint32_t cmd = (uint32_t)regs->r2;
+ switch (cmd) {
+ case __HYPERVISOR_ia64_fast_eoi:
+ regs->r8 = pirq_guest_eoi(current->domain, regs->r14);
+ break;
+ default:
+ regs->r8 = -ENOSYS;
+ }
return IA64_NO_FAULT;
}
@@ -201,8 +201,8 @@ fw_hypercall_fpswa (struct vcpu *v)
return PSCBX(v, fpswa_ret);
}
-static IA64FAULT
-fw_hypercall (struct pt_regs *regs)
+IA64FAULT
+ia64_hypercall(struct pt_regs *regs)
{
struct vcpu *v = current;
struct sal_ret_values x;
@@ -213,7 +213,13 @@ fw_hypercall (struct pt_regs *regs)
perfc_incra(fw_hypercall, index >> 8);
switch (index) {
- case FW_HYPERCALL_PAL_CALL:
+ case FW_HYPERCALL_XEN:
+ return xen_hypercall(regs);
+
+ case FW_HYPERCALL_XEN_FAST:
+ return xen_fast_hypercall(regs);
+
+ case FW_HYPERCALL_PAL_CALL:
//printf("*** PAL hypercall: index=%d\n",regs->r28);
//FIXME: This should call a C routine
#if 0
@@ -264,7 +270,7 @@ fw_hypercall (struct pt_regs *regs)
regs->r10 = y.v1; regs->r11 = y.v2;
}
break;
- case FW_HYPERCALL_SAL_CALL:
+ case FW_HYPERCALL_SAL_CALL:
x = sal_emulator(vcpu_get_gr(v,32),vcpu_get_gr(v,33),
vcpu_get_gr(v,34),vcpu_get_gr(v,35),
vcpu_get_gr(v,36),vcpu_get_gr(v,37),
@@ -272,46 +278,35 @@ fw_hypercall (struct pt_regs *regs)
regs->r8 = x.r8; regs->r9 = x.r9;
regs->r10 = x.r10; regs->r11 = x.r11;
break;
- case FW_HYPERCALL_SAL_RETURN:
+ case FW_HYPERCALL_SAL_RETURN:
if ( !test_and_set_bit(_VCPUF_down, &v->vcpu_flags) )
vcpu_sleep_nosync(v);
break;
- case FW_HYPERCALL_EFI_CALL:
+ case FW_HYPERCALL_EFI_CALL:
efi_ret_value = efi_emulator (regs, &fault);
if (fault != IA64_NO_FAULT) return fault;
regs->r8 = efi_ret_value;
break;
- case FW_HYPERCALL_IPI:
+ case FW_HYPERCALL_IPI:
fw_hypercall_ipi (regs);
break;
- case FW_HYPERCALL_SET_SHARED_INFO_VA:
+ case FW_HYPERCALL_SET_SHARED_INFO_VA:
regs->r8 = domain_set_shared_info_va (regs->r28);
break;
- case FW_HYPERCALL_FPSWA:
+ case FW_HYPERCALL_FPSWA:
fpswa_ret = fw_hypercall_fpswa (v);
regs->r8 = fpswa_ret.status;
regs->r9 = fpswa_ret.err0;
regs->r10 = fpswa_ret.err1;
regs->r11 = fpswa_ret.err2;
break;
- default:
+ default:
printf("unknown ia64 fw hypercall %lx\n", regs->r2);
regs->r8 = do_ni_hypercall();
}
return IA64_NO_FAULT;
}
-IA64FAULT
-ia64_hypercall (struct pt_regs *regs)
-{
- unsigned long index = regs->r2;
-
- if (index >= FW_HYPERCALL_FIRST_ARCH)
- return fw_hypercall (regs);
- else
- return xen_hypercall (regs);
-}
-
unsigned long hypercall_create_continuation(
unsigned int op, const char *format, ...)
{
@@ -465,28 +460,6 @@ static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
return ret;
}
-/* Legacy hypercall (as of 0x00030202). */
-static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop)
-{
- struct physdev_op op;
-
- if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
- return -EFAULT;
-
- return do_physdev_op(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
-}
-
-/* Legacy hypercall (as of 0x00030202). */
-long do_event_channel_op_compat(XEN_GUEST_HANDLE(evtchn_op_t) uop)
-{
- struct evtchn_op op;
-
- if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
- return -EFAULT;
-
- return do_event_channel_op(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
-}
-
static long register_guest_callback(struct callback_register *reg)
{
long ret = 0;
diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c
index 6c656d53eb..27f66bf7f3 100644
--- a/xen/arch/ia64/xen/mm.c
+++ b/xen/arch/ia64/xen/mm.c
@@ -172,13 +172,15 @@
#include <asm/vhpt.h>
#include <asm/vcpu.h>
#include <asm/shadow.h>
+#include <asm/p2m_entry.h>
+#include <asm/tlb_track.h>
#include <linux/efi.h>
#include <xen/guest_access.h>
#include <asm/page.h>
#include <public/memory.h>
static void domain_page_flush(struct domain* d, unsigned long mpaddr,
- unsigned long old_mfn, unsigned long new_mfn);
+ volatile pte_t* ptep, pte_t old_pte);
extern unsigned long ia64_iobase;
@@ -396,6 +398,13 @@ gmfn_to_mfn_foreign(struct domain *d, unsigned long gpfn)
{
unsigned long pte;
+ // This function may be called from __gnttab_copy()
+ // during domain destruction with VNIF copy receiver.
+ // ** FIXME: This is not SMP-safe yet about p2m table. **
+ if (unlikely(d->arch.mm.pgd == NULL)) {
+ BUG();
+ return INVALID_MFN;
+ }
pte = lookup_domain_mpa(d,gpfn << PAGE_SHIFT, NULL);
if (!pte) {
panic("gmfn_to_mfn_foreign: bad gpfn. spinning...\n");
@@ -702,6 +711,22 @@ void *domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
}
#endif
+unsigned long
+xencomm_paddr_to_maddr(unsigned long paddr)
+{
+ struct vcpu *v = current;
+ struct domain *d = v->domain;
+ u64 pa;
+
+ pa = ____lookup_domain_mpa(d, paddr);
+ if (pa == INVALID_MFN) {
+ printf("%s: called with bad memory address: 0x%lx - iip=%lx\n",
+ __func__, paddr, vcpu_regs(v)->cr_iip);
+ return 0;
+ }
+ return __va_ul((pa & _PFN_MASK) | (paddr & ~PAGE_MASK));
+}
+
/* Allocate a new page for domain and map it to the specified metaphysical
address. */
static struct page_info *
@@ -776,15 +801,18 @@ flags_to_prot (unsigned long flags)
res |= flags & ASSIGN_readonly ? _PAGE_AR_R: _PAGE_AR_RWX;
res |= flags & ASSIGN_nocache ? _PAGE_MA_UC: _PAGE_MA_WB;
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+ res |= flags & ASSIGN_tlb_track ? _PAGE_TLB_TRACKING: 0;
+#endif
return res;
}
/* map a physical address to the specified metaphysical addr */
-// flags: currently only ASSIGN_readonly, ASSIGN_nocache
+// flags: currently only ASSIGN_readonly, ASSIGN_nocache, ASSIGN_tlb_tack
// This is called by assign_domain_mmio_page().
// So accessing to pte is racy.
-void
+int
__assign_domain_page(struct domain *d,
unsigned long mpaddr, unsigned long physaddr,
unsigned long flags)
@@ -800,8 +828,25 @@ __assign_domain_page(struct domain *d,
old_pte = __pte(0);
new_pte = pfn_pte(physaddr >> PAGE_SHIFT, __pgprot(prot));
ret_pte = ptep_cmpxchg_rel(&d->arch.mm, mpaddr, pte, old_pte, new_pte);
- if (pte_val(ret_pte) == pte_val(old_pte))
+ if (pte_val(ret_pte) == pte_val(old_pte)) {
smp_mb();
+ return 0;
+ }
+
+ // dom0 tries to map real machine's I/O region, but failed.
+ // It is very likely that dom0 doesn't boot correctly because
+ // it can't access I/O. So complain here.
+ if ((flags & ASSIGN_nocache) &&
+ (pte_pfn(ret_pte) != (physaddr >> PAGE_SHIFT) ||
+ !(pte_val(ret_pte) & _PAGE_MA_UC)))
+ printk("%s:%d WARNING can't assign page domain 0x%p id %d\n"
+ "\talready assigned pte_val 0x%016lx\n"
+ "\tmpaddr 0x%016lx physaddr 0x%016lx flags 0x%lx\n",
+ __func__, __LINE__,
+ d, d->domain_id, pte_val(ret_pte),
+ mpaddr, physaddr, flags);
+
+ return -EAGAIN;
}
/* get_page() and map a physical address to the specified metaphysical addr */
@@ -818,7 +863,7 @@ assign_domain_page(struct domain *d,
set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT);
// because __assign_domain_page() uses set_pte_rel() which has
// release semantics, smp_mb() isn't needed.
- __assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable);
+ (void)__assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable);
}
int
@@ -841,8 +886,8 @@ ioports_permit_access(struct domain *d, unsigned long fp, unsigned long lp)
lp_offset = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp));
for (off = fp_offset; off <= lp_offset; off += PAGE_SIZE)
- __assign_domain_page(d, IO_PORTS_PADDR + off,
- __pa(ia64_iobase) + off, ASSIGN_nocache);
+ (void)__assign_domain_page(d, IO_PORTS_PADDR + off,
+ __pa(ia64_iobase) + off, ASSIGN_nocache);
return 0;
}
@@ -911,7 +956,7 @@ assign_domain_same_page(struct domain *d,
//XXX optimization
unsigned long end = PAGE_ALIGN(mpaddr + size);
for (mpaddr &= PAGE_MASK; mpaddr < end; mpaddr += PAGE_SIZE) {
- __assign_domain_page(d, mpaddr, mpaddr, flags);
+ (void)__assign_domain_page(d, mpaddr, mpaddr, flags);
}
}
@@ -995,7 +1040,7 @@ assign_domain_mach_page(struct domain *d,
// caller must call set_gpfn_from_mfn() before call if necessary.
// because set_gpfn_from_mfn() result must be visible before pte xchg
// caller must use memory barrier. NOTE: xchg has acquire semantics.
-// flags: currently only ASSIGN_readonly
+// flags: ASSIGN_xxx
static void
assign_domain_page_replace(struct domain *d, unsigned long mpaddr,
unsigned long mfn, unsigned long flags)
@@ -1029,12 +1074,13 @@ assign_domain_page_replace(struct domain *d, unsigned long mpaddr,
set_gpfn_from_mfn(old_mfn, INVALID_M2P_ENTRY);
}
- domain_page_flush(d, mpaddr, old_mfn, mfn);
+ domain_page_flush(d, mpaddr, pte, old_pte);
try_to_clear_PGC_allocate(d, old_page);
put_page(old_page);
}
}
+ perfc_incrc(assign_domain_page_replace);
}
// caller must get_page(new_page) before
@@ -1048,7 +1094,7 @@ assign_domain_page_cmpxchg_rel(struct domain* d, unsigned long mpaddr,
struct mm_struct *mm = &d->arch.mm;
volatile pte_t* pte;
unsigned long old_mfn;
- unsigned long old_arflags;
+ unsigned long old_prot;
pte_t old_pte;
unsigned long new_mfn;
unsigned long new_prot;
@@ -1058,12 +1104,12 @@ assign_domain_page_cmpxchg_rel(struct domain* d, unsigned long mpaddr,
pte = lookup_alloc_domain_pte(d, mpaddr);
again:
- old_arflags = pte_val(*pte) & ~_PAGE_PPN_MASK;
+ old_prot = pte_val(*pte) & ~_PAGE_PPN_MASK;
old_mfn = page_to_mfn(old_page);
- old_pte = pfn_pte(old_mfn, __pgprot(old_arflags));
+ old_pte = pfn_pte(old_mfn, __pgprot(old_prot));
if (!pte_present(old_pte)) {
- DPRINTK("%s: old_pte 0x%lx old_arflags 0x%lx old_mfn 0x%lx\n",
- __func__, pte_val(old_pte), old_arflags, old_mfn);
+ DPRINTK("%s: old_pte 0x%lx old_prot 0x%lx old_mfn 0x%lx\n",
+ __func__, pte_val(old_pte), old_prot, old_mfn);
return -EINVAL;
}
@@ -1078,10 +1124,10 @@ assign_domain_page_cmpxchg_rel(struct domain* d, unsigned long mpaddr,
goto again;
}
- DPRINTK("%s: old_pte 0x%lx old_arflags 0x%lx old_mfn 0x%lx "
+ DPRINTK("%s: old_pte 0x%lx old_prot 0x%lx old_mfn 0x%lx "
"ret_pte 0x%lx ret_mfn 0x%lx\n",
__func__,
- pte_val(old_pte), old_arflags, old_mfn,
+ pte_val(old_pte), old_prot, old_mfn,
pte_val(ret_pte), pte_pfn(ret_pte));
return -EINVAL;
}
@@ -1093,8 +1139,9 @@ assign_domain_page_cmpxchg_rel(struct domain* d, unsigned long mpaddr,
set_gpfn_from_mfn(old_mfn, INVALID_M2P_ENTRY);
- domain_page_flush(d, mpaddr, old_mfn, new_mfn);
+ domain_page_flush(d, mpaddr, pte, old_pte);
put_page(old_page);
+ perfc_incrc(assign_domain_pge_cmpxchg_rel);
return 0;
}
@@ -1161,12 +1208,13 @@ zap_domain_page_one(struct domain *d, unsigned long mpaddr, unsigned long mfn)
set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
}
- domain_page_flush(d, mpaddr, mfn, INVALID_MFN);
+ domain_page_flush(d, mpaddr, pte, old_pte);
if (page_get_owner(page) != NULL) {
try_to_clear_PGC_allocate(d, page);
}
put_page(page);
+ perfc_incrc(zap_dcomain_page_one);
}
unsigned long
@@ -1179,6 +1227,7 @@ dom0vp_zap_physmap(struct domain *d, unsigned long gpfn,
}
zap_domain_page_one(d, gpfn << PAGE_SHIFT, INVALID_MFN);
+ perfc_incrc(dom0vp_zap_physmap);
return 0;
}
@@ -1224,11 +1273,132 @@ dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn,
get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY);
assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, flags);
//don't update p2m table because this page belongs to rd, not d.
+ perfc_incrc(dom0vp_add_physmap);
out1:
put_domain(rd);
return error;
}
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
+static struct page_info* p2m_pte_zero_page = NULL;
+
+void
+expose_p2m_init(void)
+{
+ pte_t* pte;
+
+ pte = pte_alloc_one_kernel(NULL, 0);
+ BUG_ON(pte == NULL);
+ smp_mb();// make contents of the page visible.
+ p2m_pte_zero_page = virt_to_page(pte);
+}
+
+static int
+expose_p2m_page(struct domain* d, unsigned long mpaddr, struct page_info* page)
+{
+ // we can't get_page(page) here.
+ // pte page is allocated form xen heap.(see pte_alloc_one_kernel().)
+ // so that the page has NULL page owner and it's reference count
+ // is useless.
+ // see also relinquish_pte()'s page_get_owner() == NULL check.
+ BUG_ON(page_get_owner(page) != NULL);
+
+ return __assign_domain_page(d, mpaddr, page_to_maddr(page),
+ ASSIGN_readonly);
+}
+
+// It is possible to optimize loop, But this isn't performance critical.
+unsigned long
+dom0vp_expose_p2m(struct domain* d,
+ unsigned long conv_start_gpfn,
+ unsigned long assign_start_gpfn,
+ unsigned long expose_size, unsigned long granule_pfn)
+{
+ unsigned long expose_num_pfn = expose_size >> PAGE_SHIFT;
+ unsigned long i;
+ volatile pte_t* conv_pte;
+ volatile pte_t* assign_pte;
+
+ if ((expose_size % PAGE_SIZE) != 0 ||
+ (granule_pfn % PTRS_PER_PTE) != 0 ||
+ (expose_num_pfn % PTRS_PER_PTE) != 0 ||
+ (conv_start_gpfn % granule_pfn) != 0 ||
+ (assign_start_gpfn % granule_pfn) != 0 ||
+ (expose_num_pfn % granule_pfn) != 0) {
+ DPRINTK("%s conv_start_gpfn 0x%016lx assign_start_gpfn 0x%016lx "
+ "expose_size 0x%016lx granulte_pfn 0x%016lx\n", __func__,
+ conv_start_gpfn, assign_start_gpfn, expose_size, granule_pfn);
+ return -EINVAL;
+ }
+
+ if (granule_pfn != PTRS_PER_PTE) {
+ DPRINTK("%s granule_pfn 0x%016lx PTRS_PER_PTE 0x%016lx\n",
+ __func__, granule_pfn, PTRS_PER_PTE);
+ return -ENOSYS;
+ }
+
+ // allocate pgd, pmd.
+ i = conv_start_gpfn;
+ while (i < expose_num_pfn) {
+ conv_pte = lookup_noalloc_domain_pte(d, (conv_start_gpfn + i) <<
+ PAGE_SHIFT);
+ if (conv_pte == NULL) {
+ i++;
+ continue;
+ }
+
+ assign_pte = lookup_alloc_domain_pte(d, (assign_start_gpfn <<
+ PAGE_SHIFT) + i * sizeof(pte_t));
+ if (assign_pte == NULL) {
+ DPRINTK("%s failed to allocate pte page\n", __func__);
+ return -ENOMEM;
+ }
+
+ // skip to next pte page
+ i += PTRS_PER_PTE;
+ i &= ~(PTRS_PER_PTE - 1);
+ }
+
+ // expose pte page
+ i = 0;
+ while (i < expose_num_pfn) {
+ conv_pte = lookup_noalloc_domain_pte(d, (conv_start_gpfn + i) <<
+ PAGE_SHIFT);
+ if (conv_pte == NULL) {
+ i++;
+ continue;
+ }
+
+ if (expose_p2m_page(d, (assign_start_gpfn << PAGE_SHIFT) +
+ i * sizeof(pte_t), virt_to_page(conv_pte)) < 0) {
+ DPRINTK("%s failed to assign page\n", __func__);
+ return -EAGAIN;
+ }
+
+ // skip to next pte page
+ i += PTRS_PER_PTE;
+ i &= ~(PTRS_PER_PTE - 1);
+ }
+
+ // expose p2m_pte_zero_page
+ for (i = 0; i < expose_num_pfn / PTRS_PER_PTE + 1; i++) {
+ assign_pte = lookup_noalloc_domain_pte(d, (assign_start_gpfn + i) <<
+ PAGE_SHIFT);
+ BUG_ON(assign_pte == NULL);
+ if (pte_present(*assign_pte)) {
+ continue;
+ }
+ if (expose_p2m_page(d, (assign_start_gpfn + i) << PAGE_SHIFT,
+ p2m_pte_zero_page) < 0) {
+ DPRINTK("%s failed to assign zero-pte page\n", __func__);
+ return -EAGAIN;
+ }
+ }
+
+ return 0;
+}
+#endif
+
// grant table host mapping
// mpaddr: host_addr: pseudo physical address
// mfn: frame: machine page frame
@@ -1253,8 +1423,13 @@ create_grant_host_mapping(unsigned long gpaddr,
BUG_ON(ret == 0);
BUG_ON(page_get_owner(mfn_to_page(mfn)) == d &&
get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY);
- assign_domain_page_replace(d, gpaddr, mfn, (flags & GNTMAP_readonly)?
- ASSIGN_readonly: ASSIGN_writable);
+ assign_domain_page_replace(d, gpaddr, mfn,
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+ ASSIGN_tlb_track |
+#endif
+ ((flags & GNTMAP_readonly) ?
+ ASSIGN_readonly : ASSIGN_writable));
+ perfc_incrc(create_grant_host_mapping);
return GNTST_okay;
}
@@ -1308,12 +1483,13 @@ destroy_grant_host_mapping(unsigned long gpaddr,
}
BUG_ON(pte_pfn(old_pte) != mfn);
- domain_page_flush(d, gpaddr, mfn, INVALID_MFN);
+ domain_page_flush(d, gpaddr, pte, old_pte);
page = mfn_to_page(mfn);
BUG_ON(page_get_owner(page) == d);//try_to_clear_PGC_allocate(d, page) is not needed.
put_page(page);
+ perfc_incrc(destroy_grant_host_mapping);
return GNTST_okay;
}
@@ -1374,6 +1550,7 @@ steal_page(struct domain *d, struct page_info *page, unsigned int memflags)
free_domheap_page(new);
return -1;
}
+ perfc_incrc(steal_page_refcount);
}
spin_lock(&d->page_alloc_lock);
@@ -1443,6 +1620,7 @@ steal_page(struct domain *d, struct page_info *page, unsigned int memflags)
list_del(&page->list);
spin_unlock(&d->page_alloc_lock);
+ perfc_incrc(steal_page);
return 0;
}
@@ -1460,6 +1638,8 @@ guest_physmap_add_page(struct domain *d, unsigned long gpfn,
assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, ASSIGN_writable);
//BUG_ON(mfn != ((lookup_domain_mpa(d, gpfn << PAGE_SHIFT) & _PFN_MASK) >> PAGE_SHIFT));
+
+ perfc_incrc(guest_physmap_add_page);
}
void
@@ -1468,18 +1648,51 @@ guest_physmap_remove_page(struct domain *d, unsigned long gpfn,
{
BUG_ON(mfn == 0);//XXX
zap_domain_page_one(d, gpfn << PAGE_SHIFT, mfn);
+ perfc_incrc(guest_physmap_remove_page);
}
//XXX sledgehammer.
// flush finer range.
static void
domain_page_flush(struct domain* d, unsigned long mpaddr,
- unsigned long old_mfn, unsigned long new_mfn)
+ volatile pte_t* ptep, pte_t old_pte)
{
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+ struct tlb_track_entry* entry;
+#endif
+
if (shadow_mode_enabled(d))
shadow_mark_page_dirty(d, mpaddr >> PAGE_SHIFT);
+#ifndef CONFIG_XEN_IA64_TLB_TRACK
domain_flush_vtlb_all();
+#else
+ switch (tlb_track_search_and_remove(d->arch.tlb_track,
+ ptep, old_pte, &entry)) {
+ case TLB_TRACK_NOT_TRACKED:
+ // DPRINTK("%s TLB_TRACK_NOT_TRACKED\n", __func__);
+ domain_flush_vtlb_all();
+ break;
+ case TLB_TRACK_NOT_FOUND:
+ /* do nothing */
+ // DPRINTK("%s TLB_TRACK_NOT_FOUND\n", __func__);
+ break;
+ case TLB_TRACK_FOUND:
+ // DPRINTK("%s TLB_TRACK_FOUND\n", __func__);
+ domain_flush_vtlb_track_entry(d, entry);
+ tlb_track_free_entry(d->arch.tlb_track, entry);
+ break;
+ case TLB_TRACK_MANY:
+ DPRINTK("%s TLB_TRACK_MANY\n", __func__);
+ domain_flush_vtlb_all();
+ break;
+ case TLB_TRACK_AGAIN:
+ DPRINTK("%s TLB_TRACK_AGAIN\n", __func__);
+ BUG();
+ break;
+ }
+#endif
+ perfc_incrc(domain_page_flush);
}
int
diff --git a/xen/arch/ia64/xen/privop.c b/xen/arch/ia64/xen/privop.c
index 31e1ebc198..be94c3d6f8 100644
--- a/xen/arch/ia64/xen/privop.c
+++ b/xen/arch/ia64/xen/privop.c
@@ -9,13 +9,13 @@
#include <asm/privop.h>
#include <asm/vcpu.h>
#include <asm/processor.h>
-#include <asm/delay.h> // Debug only
+#include <asm/delay.h> // Debug only
#include <asm/dom_fw.h>
#include <asm/vhpt.h>
#include <asm/bundle.h>
#include <xen/perfc.h>
-long priv_verbose=0;
+long priv_verbose = 0;
unsigned long privop_trace = 0;
/* Set to 1 to handle privified instructions from the privify tool. */
@@ -29,200 +29,213 @@ static const int privify_en = 1;
Privileged operation emulation routines
**************************************************************************/
-static IA64FAULT priv_rfi(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_rfi(VCPU * vcpu, INST64 inst)
{
return vcpu_rfi(vcpu);
}
-static IA64FAULT priv_bsw0(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_bsw0(VCPU * vcpu, INST64 inst)
{
return vcpu_bsw0(vcpu);
}
-static IA64FAULT priv_bsw1(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_bsw1(VCPU * vcpu, INST64 inst)
{
return vcpu_bsw1(vcpu);
}
-static IA64FAULT priv_cover(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_cover(VCPU * vcpu, INST64 inst)
{
return vcpu_cover(vcpu);
}
-static IA64FAULT priv_ptc_l(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_ptc_l(VCPU * vcpu, INST64 inst)
{
- UINT64 vadr = vcpu_get_gr(vcpu,inst.M45.r3);
- UINT64 log_range;
+ u64 vadr = vcpu_get_gr(vcpu, inst.M45.r3);
+ u64 log_range;
- log_range = ((vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2);
- return vcpu_ptc_l(vcpu,vadr,log_range);
+ log_range = ((vcpu_get_gr(vcpu, inst.M45.r2) & 0xfc) >> 2);
+ return vcpu_ptc_l(vcpu, vadr, log_range);
}
-static IA64FAULT priv_ptc_e(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_ptc_e(VCPU * vcpu, INST64 inst)
{
- UINT src = inst.M28.r3;
+ unsigned int src = inst.M28.r3;
// NOTE: ptc_e with source gr > 63 is emulated as a fc r(y-64)
if (privify_en && src > 63)
- return(vcpu_fc(vcpu,vcpu_get_gr(vcpu,src - 64)));
- return vcpu_ptc_e(vcpu,vcpu_get_gr(vcpu,src));
+ return vcpu_fc(vcpu, vcpu_get_gr(vcpu, src - 64));
+ return vcpu_ptc_e(vcpu, vcpu_get_gr(vcpu, src));
}
-static IA64FAULT priv_ptc_g(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_ptc_g(VCPU * vcpu, INST64 inst)
{
- UINT64 vadr = vcpu_get_gr(vcpu,inst.M45.r3);
- UINT64 addr_range;
+ u64 vadr = vcpu_get_gr(vcpu, inst.M45.r3);
+ u64 addr_range;
- addr_range = 1 << ((vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2);
- return vcpu_ptc_g(vcpu,vadr,addr_range);
+ addr_range = 1 << ((vcpu_get_gr(vcpu, inst.M45.r2) & 0xfc) >> 2);
+ return vcpu_ptc_g(vcpu, vadr, addr_range);
}
-static IA64FAULT priv_ptc_ga(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_ptc_ga(VCPU * vcpu, INST64 inst)
{
- UINT64 vadr = vcpu_get_gr(vcpu,inst.M45.r3);
- UINT64 addr_range;
+ u64 vadr = vcpu_get_gr(vcpu, inst.M45.r3);
+ u64 addr_range;
- addr_range = 1 << ((vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2);
- return vcpu_ptc_ga(vcpu,vadr,addr_range);
+ addr_range = 1 << ((vcpu_get_gr(vcpu, inst.M45.r2) & 0xfc) >> 2);
+ return vcpu_ptc_ga(vcpu, vadr, addr_range);
}
-static IA64FAULT priv_ptr_d(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_ptr_d(VCPU * vcpu, INST64 inst)
{
- UINT64 vadr = vcpu_get_gr(vcpu,inst.M45.r3);
- UINT64 log_range;
+ u64 vadr = vcpu_get_gr(vcpu, inst.M45.r3);
+ u64 log_range;
- log_range = (vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2;
- return vcpu_ptr_d(vcpu,vadr,log_range);
+ log_range = (vcpu_get_gr(vcpu, inst.M45.r2) & 0xfc) >> 2;
+ return vcpu_ptr_d(vcpu, vadr, log_range);
}
-static IA64FAULT priv_ptr_i(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_ptr_i(VCPU * vcpu, INST64 inst)
{
- UINT64 vadr = vcpu_get_gr(vcpu,inst.M45.r3);
- UINT64 log_range;
+ u64 vadr = vcpu_get_gr(vcpu, inst.M45.r3);
+ u64 log_range;
- log_range = (vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2;
- return vcpu_ptr_i(vcpu,vadr,log_range);
+ log_range = (vcpu_get_gr(vcpu, inst.M45.r2) & 0xfc) >> 2;
+ return vcpu_ptr_i(vcpu, vadr, log_range);
}
-static IA64FAULT priv_tpa(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_tpa(VCPU * vcpu, INST64 inst)
{
- UINT64 padr;
- UINT fault;
- UINT src = inst.M46.r3;
+ u64 padr;
+ unsigned int fault;
+ unsigned int src = inst.M46.r3;
// NOTE: tpa with source gr > 63 is emulated as a ttag rx=r(y-64)
if (privify_en && src > 63)
- fault = vcpu_ttag(vcpu,vcpu_get_gr(vcpu,src-64),&padr);
- else fault = vcpu_tpa(vcpu,vcpu_get_gr(vcpu,src),&padr);
+ fault = vcpu_ttag(vcpu, vcpu_get_gr(vcpu, src - 64), &padr);
+ else
+ fault = vcpu_tpa(vcpu, vcpu_get_gr(vcpu, src), &padr);
if (fault == IA64_NO_FAULT)
return vcpu_set_gr(vcpu, inst.M46.r1, padr, 0);
- else return fault;
+ else
+ return fault;
}
-static IA64FAULT priv_tak(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_tak(VCPU * vcpu, INST64 inst)
{
- UINT64 key;
- UINT fault;
- UINT src = inst.M46.r3;
+ u64 key;
+ unsigned int fault;
+ unsigned int src = inst.M46.r3;
// NOTE: tak with source gr > 63 is emulated as a thash rx=r(y-64)
if (privify_en && src > 63)
- fault = vcpu_thash(vcpu,vcpu_get_gr(vcpu,src-64),&key);
- else fault = vcpu_tak(vcpu,vcpu_get_gr(vcpu,src),&key);
+ fault = vcpu_thash(vcpu, vcpu_get_gr(vcpu, src - 64), &key);
+ else
+ fault = vcpu_tak(vcpu, vcpu_get_gr(vcpu, src), &key);
if (fault == IA64_NO_FAULT)
- return vcpu_set_gr(vcpu, inst.M46.r1, key,0);
- else return fault;
+ return vcpu_set_gr(vcpu, inst.M46.r1, key, 0);
+ else
+ return fault;
}
/************************************
* Insert translation register/cache
************************************/
-static IA64FAULT priv_itr_d(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_itr_d(VCPU * vcpu, INST64 inst)
{
- UINT64 fault, itir, ifa, pte, slot;
+ u64 fault, itir, ifa, pte, slot;
- //if (!vcpu_get_psr_ic(vcpu)) return(IA64_ILLOP_FAULT);
- if ((fault = vcpu_get_itir(vcpu,&itir)) != IA64_NO_FAULT)
- return(IA64_ILLOP_FAULT);
- if ((fault = vcpu_get_ifa(vcpu,&ifa)) != IA64_NO_FAULT)
- return(IA64_ILLOP_FAULT);
- pte = vcpu_get_gr(vcpu,inst.M42.r2);
- slot = vcpu_get_gr(vcpu,inst.M42.r3);
+ //if (!vcpu_get_psr_ic(vcpu))
+ // return IA64_ILLOP_FAULT;
+ fault = vcpu_get_itir(vcpu, &itir);
+ if (fault != IA64_NO_FAULT)
+ return IA64_ILLOP_FAULT;
+ fault = vcpu_get_ifa(vcpu, &ifa);
+ if (fault != IA64_NO_FAULT)
+ return IA64_ILLOP_FAULT;
+ pte = vcpu_get_gr(vcpu, inst.M42.r2);
+ slot = vcpu_get_gr(vcpu, inst.M42.r3);
- return (vcpu_itr_d(vcpu,slot,pte,itir,ifa));
+ return vcpu_itr_d(vcpu, slot, pte, itir, ifa);
}
-static IA64FAULT priv_itr_i(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_itr_i(VCPU * vcpu, INST64 inst)
{
- UINT64 fault, itir, ifa, pte, slot;
+ u64 fault, itir, ifa, pte, slot;
- //if (!vcpu_get_psr_ic(vcpu)) return(IA64_ILLOP_FAULT);
- if ((fault = vcpu_get_itir(vcpu,&itir)) != IA64_NO_FAULT)
- return(IA64_ILLOP_FAULT);
- if ((fault = vcpu_get_ifa(vcpu,&ifa)) != IA64_NO_FAULT)
- return(IA64_ILLOP_FAULT);
- pte = vcpu_get_gr(vcpu,inst.M42.r2);
- slot = vcpu_get_gr(vcpu,inst.M42.r3);
+ //if (!vcpu_get_psr_ic(vcpu)) return IA64_ILLOP_FAULT;
+ fault = vcpu_get_itir(vcpu, &itir);
+ if (fault != IA64_NO_FAULT)
+ return IA64_ILLOP_FAULT;
+ fault = vcpu_get_ifa(vcpu, &ifa);
+ if (fault != IA64_NO_FAULT)
+ return IA64_ILLOP_FAULT;
+ pte = vcpu_get_gr(vcpu, inst.M42.r2);
+ slot = vcpu_get_gr(vcpu, inst.M42.r3);
- return (vcpu_itr_i(vcpu,slot,pte,itir,ifa));
+ return vcpu_itr_i(vcpu, slot, pte, itir, ifa);
}
-static IA64FAULT priv_itc_d(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_itc_d(VCPU * vcpu, INST64 inst)
{
- UINT64 fault, itir, ifa, pte;
+ u64 fault, itir, ifa, pte;
- //if (!vcpu_get_psr_ic(vcpu)) return(IA64_ILLOP_FAULT);
- if ((fault = vcpu_get_itir(vcpu,&itir)) != IA64_NO_FAULT)
- return(IA64_ILLOP_FAULT);
- if ((fault = vcpu_get_ifa(vcpu,&ifa)) != IA64_NO_FAULT)
- return(IA64_ILLOP_FAULT);
- pte = vcpu_get_gr(vcpu,inst.M41.r2);
+ //if (!vcpu_get_psr_ic(vcpu)) return IA64_ILLOP_FAULT;
+ fault = vcpu_get_itir(vcpu, &itir);
+ if (fault != IA64_NO_FAULT)
+ return IA64_ILLOP_FAULT;
+ fault = vcpu_get_ifa(vcpu, &ifa);
+ if (fault != IA64_NO_FAULT)
+ return IA64_ILLOP_FAULT;
+ pte = vcpu_get_gr(vcpu, inst.M41.r2);
- return (vcpu_itc_d(vcpu,pte,itir,ifa));
+ return vcpu_itc_d(vcpu, pte, itir, ifa);
}
-static IA64FAULT priv_itc_i(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_itc_i(VCPU * vcpu, INST64 inst)
{
- UINT64 fault, itir, ifa, pte;
+ u64 fault, itir, ifa, pte;
- //if (!vcpu_get_psr_ic(vcpu)) return(IA64_ILLOP_FAULT);
- if ((fault = vcpu_get_itir(vcpu,&itir)) != IA64_NO_FAULT)
- return(IA64_ILLOP_FAULT);
- if ((fault = vcpu_get_ifa(vcpu,&ifa)) != IA64_NO_FAULT)
- return(IA64_ILLOP_FAULT);
- pte = vcpu_get_gr(vcpu,inst.M41.r2);
+ //if (!vcpu_get_psr_ic(vcpu)) return IA64_ILLOP_FAULT;
+ fault = vcpu_get_itir(vcpu, &itir);
+ if (fault != IA64_NO_FAULT)
+ return IA64_ILLOP_FAULT;
+ fault = vcpu_get_ifa(vcpu, &ifa);
+ if (fault != IA64_NO_FAULT)
+ return IA64_ILLOP_FAULT;
+ pte = vcpu_get_gr(vcpu, inst.M41.r2);
- return (vcpu_itc_i(vcpu,pte,itir,ifa));
+ return vcpu_itc_i(vcpu, pte, itir, ifa);
}
/*************************************
* Moves to semi-privileged registers
*************************************/
-static IA64FAULT priv_mov_to_ar_imm(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_ar_imm(VCPU * vcpu, INST64 inst)
{
// I27 and M30 are identical for these fields
- UINT64 ar3 = inst.M30.ar3;
- UINT64 imm = vcpu_get_gr(vcpu,inst.M30.imm);
- return (vcpu_set_ar(vcpu,ar3,imm));
+ u64 ar3 = inst.M30.ar3;
+ u64 imm = vcpu_get_gr(vcpu, inst.M30.imm);
+ return vcpu_set_ar(vcpu, ar3, imm);
}
-static IA64FAULT priv_mov_to_ar_reg(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_ar_reg(VCPU * vcpu, INST64 inst)
{
// I26 and M29 are identical for these fields
- UINT64 ar3 = inst.M29.ar3;
+ u64 ar3 = inst.M29.ar3;
if (privify_en && inst.M29.r2 > 63 && inst.M29.ar3 < 8) {
// privified mov from kr
- UINT64 val;
- if (vcpu_get_ar(vcpu,ar3,&val) != IA64_ILLOP_FAULT)
- return vcpu_set_gr(vcpu, inst.M29.r2-64, val,0);
- else return IA64_ILLOP_FAULT;
- }
- else {
- UINT64 r2 = vcpu_get_gr(vcpu,inst.M29.r2);
- return (vcpu_set_ar(vcpu,ar3,r2));
+ u64 val;
+ if (vcpu_get_ar(vcpu, ar3, &val) != IA64_ILLOP_FAULT)
+ return vcpu_set_gr(vcpu, inst.M29.r2 - 64, val, 0);
+ else
+ return IA64_ILLOP_FAULT;
+ } else {
+ u64 r2 = vcpu_get_gr(vcpu, inst.M29.r2);
+ return vcpu_set_ar(vcpu, ar3, r2);
}
}
@@ -230,177 +243,205 @@ static IA64FAULT priv_mov_to_ar_reg(VCPU *vcpu, INST64 inst)
* Moves to privileged registers
********************************/
-static IA64FAULT priv_mov_to_pkr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_pkr(VCPU * vcpu, INST64 inst)
{
- UINT64 r3 = vcpu_get_gr(vcpu,inst.M42.r3);
- UINT64 r2 = vcpu_get_gr(vcpu,inst.M42.r2);
- return (vcpu_set_pkr(vcpu,r3,r2));
+ u64 r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+ u64 r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+ return vcpu_set_pkr(vcpu, r3, r2);
}
-static IA64FAULT priv_mov_to_rr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_rr(VCPU * vcpu, INST64 inst)
{
- UINT64 r3 = vcpu_get_gr(vcpu,inst.M42.r3);
- UINT64 r2 = vcpu_get_gr(vcpu,inst.M42.r2);
- return (vcpu_set_rr(vcpu,r3,r2));
+ u64 r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+ u64 r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+ return vcpu_set_rr(vcpu, r3, r2);
}
-static IA64FAULT priv_mov_to_dbr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_dbr(VCPU * vcpu, INST64 inst)
{
- UINT64 r3 = vcpu_get_gr(vcpu,inst.M42.r3);
- UINT64 r2 = vcpu_get_gr(vcpu,inst.M42.r2);
- return (vcpu_set_dbr(vcpu,r3,r2));
+ u64 r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+ u64 r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+ return vcpu_set_dbr(vcpu, r3, r2);
}
-static IA64FAULT priv_mov_to_ibr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_ibr(VCPU * vcpu, INST64 inst)
{
- UINT64 r3 = vcpu_get_gr(vcpu,inst.M42.r3);
- UINT64 r2 = vcpu_get_gr(vcpu,inst.M42.r2);
- return (vcpu_set_ibr(vcpu,r3,r2));
+ u64 r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+ u64 r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+ return vcpu_set_ibr(vcpu, r3, r2);
}
-static IA64FAULT priv_mov_to_pmc(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_pmc(VCPU * vcpu, INST64 inst)
{
- UINT64 r3 = vcpu_get_gr(vcpu,inst.M42.r3);
- UINT64 r2 = vcpu_get_gr(vcpu,inst.M42.r2);
- return (vcpu_set_pmc(vcpu,r3,r2));
+ u64 r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+ u64 r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+ return vcpu_set_pmc(vcpu, r3, r2);
}
-static IA64FAULT priv_mov_to_pmd(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_pmd(VCPU * vcpu, INST64 inst)
{
- UINT64 r3 = vcpu_get_gr(vcpu,inst.M42.r3);
- UINT64 r2 = vcpu_get_gr(vcpu,inst.M42.r2);
- return (vcpu_set_pmd(vcpu,r3,r2));
+ u64 r3 = vcpu_get_gr(vcpu, inst.M42.r3);
+ u64 r2 = vcpu_get_gr(vcpu, inst.M42.r2);
+ return vcpu_set_pmd(vcpu, r3, r2);
}
-static IA64FAULT priv_mov_to_cr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_cr(VCPU * vcpu, INST64 inst)
{
- UINT64 val = vcpu_get_gr(vcpu, inst.M32.r2);
+ u64 val = vcpu_get_gr(vcpu, inst.M32.r2);
perfc_incra(mov_to_cr, inst.M32.cr3);
switch (inst.M32.cr3) {
- case 0: return vcpu_set_dcr(vcpu,val);
- case 1: return vcpu_set_itm(vcpu,val);
- case 2: return vcpu_set_iva(vcpu,val);
- case 8: return vcpu_set_pta(vcpu,val);
- case 16:return vcpu_set_ipsr(vcpu,val);
- case 17:return vcpu_set_isr(vcpu,val);
- case 19:return vcpu_set_iip(vcpu,val);
- case 20:return vcpu_set_ifa(vcpu,val);
- case 21:return vcpu_set_itir(vcpu,val);
- case 22:return vcpu_set_iipa(vcpu,val);
- case 23:return vcpu_set_ifs(vcpu,val);
- case 24:return vcpu_set_iim(vcpu,val);
- case 25:return vcpu_set_iha(vcpu,val);
- case 64:return vcpu_set_lid(vcpu,val);
- case 65:return IA64_ILLOP_FAULT;
- case 66:return vcpu_set_tpr(vcpu,val);
- case 67:return vcpu_set_eoi(vcpu,val);
- case 68:return IA64_ILLOP_FAULT;
- case 69:return IA64_ILLOP_FAULT;
- case 70:return IA64_ILLOP_FAULT;
- case 71:return IA64_ILLOP_FAULT;
- case 72:return vcpu_set_itv(vcpu,val);
- case 73:return vcpu_set_pmv(vcpu,val);
- case 74:return vcpu_set_cmcv(vcpu,val);
- case 80:return vcpu_set_lrr0(vcpu,val);
- case 81:return vcpu_set_lrr1(vcpu,val);
- default: return IA64_ILLOP_FAULT;
+ case 0:
+ return vcpu_set_dcr(vcpu, val);
+ case 1:
+ return vcpu_set_itm(vcpu, val);
+ case 2:
+ return vcpu_set_iva(vcpu, val);
+ case 8:
+ return vcpu_set_pta(vcpu, val);
+ case 16:
+ return vcpu_set_ipsr(vcpu, val);
+ case 17:
+ return vcpu_set_isr(vcpu, val);
+ case 19:
+ return vcpu_set_iip(vcpu, val);
+ case 20:
+ return vcpu_set_ifa(vcpu, val);
+ case 21:
+ return vcpu_set_itir(vcpu, val);
+ case 22:
+ return vcpu_set_iipa(vcpu, val);
+ case 23:
+ return vcpu_set_ifs(vcpu, val);
+ case 24:
+ return vcpu_set_iim(vcpu, val);
+ case 25:
+ return vcpu_set_iha(vcpu, val);
+ case 64:
+ return vcpu_set_lid(vcpu, val);
+ case 65:
+ return IA64_ILLOP_FAULT;
+ case 66:
+ return vcpu_set_tpr(vcpu, val);
+ case 67:
+ return vcpu_set_eoi(vcpu, val);
+ case 68:
+ return IA64_ILLOP_FAULT;
+ case 69:
+ return IA64_ILLOP_FAULT;
+ case 70:
+ return IA64_ILLOP_FAULT;
+ case 71:
+ return IA64_ILLOP_FAULT;
+ case 72:
+ return vcpu_set_itv(vcpu, val);
+ case 73:
+ return vcpu_set_pmv(vcpu, val);
+ case 74:
+ return vcpu_set_cmcv(vcpu, val);
+ case 80:
+ return vcpu_set_lrr0(vcpu, val);
+ case 81:
+ return vcpu_set_lrr1(vcpu, val);
+ default:
+ return IA64_ILLOP_FAULT;
}
}
-static IA64FAULT priv_rsm(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_rsm(VCPU * vcpu, INST64 inst)
{
- UINT64 imm24 = (inst.M44.i<<23)|(inst.M44.i2<<21)|inst.M44.imm;
- return vcpu_reset_psr_sm(vcpu,imm24);
+ u64 imm24 = (inst.M44.i << 23) | (inst.M44.i2 << 21) | inst.M44.imm;
+ return vcpu_reset_psr_sm(vcpu, imm24);
}
-static IA64FAULT priv_ssm(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_ssm(VCPU * vcpu, INST64 inst)
{
- UINT64 imm24 = (inst.M44.i<<23)|(inst.M44.i2<<21)|inst.M44.imm;
- return vcpu_set_psr_sm(vcpu,imm24);
+ u64 imm24 = (inst.M44.i << 23) | (inst.M44.i2 << 21) | inst.M44.imm;
+ return vcpu_set_psr_sm(vcpu, imm24);
}
/**
* @todo Check for reserved bits and return IA64_RSVDREG_FAULT.
*/
-static IA64FAULT priv_mov_to_psr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_to_psr(VCPU * vcpu, INST64 inst)
{
- UINT64 val = vcpu_get_gr(vcpu, inst.M35.r2);
- return vcpu_set_psr_l(vcpu,val);
+ u64 val = vcpu_get_gr(vcpu, inst.M35.r2);
+ return vcpu_set_psr_l(vcpu, val);
}
/**********************************
* Moves from privileged registers
**********************************/
-static IA64FAULT priv_mov_from_rr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_from_rr(VCPU * vcpu, INST64 inst)
{
- UINT64 val;
+ u64 val;
IA64FAULT fault;
- UINT64 reg;
-
- reg = vcpu_get_gr(vcpu,inst.M43.r3);
+ u64 reg;
+
+ reg = vcpu_get_gr(vcpu, inst.M43.r3);
if (privify_en && inst.M43.r1 > 63) {
// privified mov from cpuid
- fault = vcpu_get_cpuid(vcpu,reg,&val);
+ fault = vcpu_get_cpuid(vcpu, reg, &val);
if (fault == IA64_NO_FAULT)
- return vcpu_set_gr(vcpu, inst.M43.r1-64, val, 0);
- }
- else {
- fault = vcpu_get_rr(vcpu,reg,&val);
+ return vcpu_set_gr(vcpu, inst.M43.r1 - 64, val, 0);
+ } else {
+ fault = vcpu_get_rr(vcpu, reg, &val);
if (fault == IA64_NO_FAULT)
return vcpu_set_gr(vcpu, inst.M43.r1, val, 0);
}
return fault;
}
-static IA64FAULT priv_mov_from_pkr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_from_pkr(VCPU * vcpu, INST64 inst)
{
- UINT64 val;
+ u64 val;
IA64FAULT fault;
-
- fault = vcpu_get_pkr(vcpu,vcpu_get_gr(vcpu,inst.M43.r3),&val);
+
+ fault = vcpu_get_pkr(vcpu, vcpu_get_gr(vcpu, inst.M43.r3), &val);
if (fault == IA64_NO_FAULT)
return vcpu_set_gr(vcpu, inst.M43.r1, val, 0);
- else return fault;
+ else
+ return fault;
}
-static IA64FAULT priv_mov_from_dbr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_from_dbr(VCPU * vcpu, INST64 inst)
{
- UINT64 val;
+ u64 val;
IA64FAULT fault;
-
- fault = vcpu_get_dbr(vcpu,vcpu_get_gr(vcpu,inst.M43.r3),&val);
+
+ fault = vcpu_get_dbr(vcpu, vcpu_get_gr(vcpu, inst.M43.r3), &val);
if (fault == IA64_NO_FAULT)
return vcpu_set_gr(vcpu, inst.M43.r1, val, 0);
- else return fault;
+ else
+ return fault;
}
-static IA64FAULT priv_mov_from_ibr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_from_ibr(VCPU * vcpu, INST64 inst)
{
- UINT64 val;
+ u64 val;
IA64FAULT fault;
-
- fault = vcpu_get_ibr(vcpu,vcpu_get_gr(vcpu,inst.M43.r3),&val);
+
+ fault = vcpu_get_ibr(vcpu, vcpu_get_gr(vcpu, inst.M43.r3), &val);
if (fault == IA64_NO_FAULT)
return vcpu_set_gr(vcpu, inst.M43.r1, val, 0);
- else return fault;
+ else
+ return fault;
}
-static IA64FAULT priv_mov_from_pmc(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_from_pmc(VCPU * vcpu, INST64 inst)
{
- UINT64 val;
+ u64 val;
IA64FAULT fault;
- UINT64 reg;
-
- reg = vcpu_get_gr(vcpu,inst.M43.r3);
+ u64 reg;
+
+ reg = vcpu_get_gr(vcpu, inst.M43.r3);
if (privify_en && inst.M43.r1 > 63) {
// privified mov from pmd
- fault = vcpu_get_pmd(vcpu,reg,&val);
+ fault = vcpu_get_pmd(vcpu, reg, &val);
if (fault == IA64_NO_FAULT)
- return vcpu_set_gr(vcpu, inst.M43.r1-64, val, 0);
- }
- else {
- fault = vcpu_get_pmc(vcpu,reg,&val);
+ return vcpu_set_gr(vcpu, inst.M43.r1 - 64, val, 0);
+ } else {
+ fault = vcpu_get_pmc(vcpu, reg, &val);
if (fault == IA64_NO_FAULT)
return vcpu_set_gr(vcpu, inst.M43.r1, val, 0);
}
@@ -410,55 +451,84 @@ static IA64FAULT priv_mov_from_pmc(VCPU *vcpu, INST64 inst)
#define cr_get(cr) \
((fault = vcpu_get_##cr(vcpu,&val)) == IA64_NO_FAULT) ? \
vcpu_set_gr(vcpu, tgt, val, 0) : fault;
-
-static IA64FAULT priv_mov_from_cr(VCPU *vcpu, INST64 inst)
+
+static IA64FAULT priv_mov_from_cr(VCPU * vcpu, INST64 inst)
{
- UINT64 tgt = inst.M33.r1;
- UINT64 val;
+ u64 tgt = inst.M33.r1;
+ u64 val;
IA64FAULT fault;
perfc_incra(mov_from_cr, inst.M33.cr3);
switch (inst.M33.cr3) {
- case 0: return cr_get(dcr);
- case 1: return cr_get(itm);
- case 2: return cr_get(iva);
- case 8: return cr_get(pta);
- case 16:return cr_get(ipsr);
- case 17:return cr_get(isr);
- case 19:return cr_get(iip);
- case 20:return cr_get(ifa);
- case 21:return cr_get(itir);
- case 22:return cr_get(iipa);
- case 23:return cr_get(ifs);
- case 24:return cr_get(iim);
- case 25:return cr_get(iha);
- case 64:return cr_get(lid);
- case 65:return cr_get(ivr);
- case 66:return cr_get(tpr);
- case 67:return vcpu_set_gr(vcpu,tgt,0L,0);
- case 68:return cr_get(irr0);
- case 69:return cr_get(irr1);
- case 70:return cr_get(irr2);
- case 71:return cr_get(irr3);
- case 72:return cr_get(itv);
- case 73:return cr_get(pmv);
- case 74:return cr_get(cmcv);
- case 80:return cr_get(lrr0);
- case 81:return cr_get(lrr1);
- default: return IA64_ILLOP_FAULT;
+ case 0:
+ return cr_get(dcr);
+ case 1:
+ return cr_get(itm);
+ case 2:
+ return cr_get(iva);
+ case 8:
+ return cr_get(pta);
+ case 16:
+ return cr_get(ipsr);
+ case 17:
+ return cr_get(isr);
+ case 19:
+ return cr_get(iip);
+ case 20:
+ return cr_get(ifa);
+ case 21:
+ return cr_get(itir);
+ case 22:
+ return cr_get(iipa);
+ case 23:
+ return cr_get(ifs);
+ case 24:
+ return cr_get(iim);
+ case 25:
+ return cr_get(iha);
+ case 64:
+ return cr_get(lid);
+ case 65:
+ return cr_get(ivr);
+ case 66:
+ return cr_get(tpr);
+ case 67:
+ return vcpu_set_gr(vcpu, tgt, 0L, 0);
+ case 68:
+ return cr_get(irr0);
+ case 69:
+ return cr_get(irr1);
+ case 70:
+ return cr_get(irr2);
+ case 71:
+ return cr_get(irr3);
+ case 72:
+ return cr_get(itv);
+ case 73:
+ return cr_get(pmv);
+ case 74:
+ return cr_get(cmcv);
+ case 80:
+ return cr_get(lrr0);
+ case 81:
+ return cr_get(lrr1);
+ default:
+ return IA64_ILLOP_FAULT;
}
return IA64_ILLOP_FAULT;
}
-static IA64FAULT priv_mov_from_psr(VCPU *vcpu, INST64 inst)
+static IA64FAULT priv_mov_from_psr(VCPU * vcpu, INST64 inst)
{
- UINT64 tgt = inst.M33.r1;
- UINT64 val;
+ u64 tgt = inst.M33.r1;
+ u64 val;
IA64FAULT fault;
- if ((fault = vcpu_get_psr(vcpu,&val)) == IA64_NO_FAULT)
+ fault = vcpu_get_psr(vcpu, &val);
+ if (fault == IA64_NO_FAULT)
return vcpu_set_gr(vcpu, tgt, val, 0);
- else return fault;
+ else
+ return fault;
}
/**************************************************************************
@@ -483,28 +553,28 @@ static const IA64_SLOT_TYPE slot_types[0x20][3] = {
};
// pointer to privileged emulation function
-typedef IA64FAULT (*PPEFCN)(VCPU *vcpu, INST64 inst);
+typedef IA64FAULT(*PPEFCN) (VCPU * vcpu, INST64 inst);
static const PPEFCN Mpriv_funcs[64] = {
- priv_mov_to_rr, priv_mov_to_dbr, priv_mov_to_ibr, priv_mov_to_pkr,
- priv_mov_to_pmc, priv_mov_to_pmd, 0, 0,
- 0, priv_ptc_l, priv_ptc_g, priv_ptc_ga,
- priv_ptr_d, priv_ptr_i, priv_itr_d, priv_itr_i,
- priv_mov_from_rr, priv_mov_from_dbr, priv_mov_from_ibr, priv_mov_from_pkr,
- priv_mov_from_pmc, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, priv_tpa, priv_tak,
- 0, 0, 0, 0,
- priv_mov_from_cr, priv_mov_from_psr, 0, 0,
- 0, 0, 0, 0,
- priv_mov_to_cr, priv_mov_to_psr, priv_itc_d, priv_itc_i,
- 0, 0, 0, 0,
- priv_ptc_e, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+ priv_mov_to_rr, priv_mov_to_dbr, priv_mov_to_ibr, priv_mov_to_pkr,
+ priv_mov_to_pmc, priv_mov_to_pmd, 0, 0,
+ 0, priv_ptc_l, priv_ptc_g, priv_ptc_ga,
+ priv_ptr_d, priv_ptr_i, priv_itr_d, priv_itr_i,
+ priv_mov_from_rr, priv_mov_from_dbr, priv_mov_from_ibr,
+ priv_mov_from_pkr,
+ priv_mov_from_pmc, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, priv_tpa, priv_tak,
+ 0, 0, 0, 0,
+ priv_mov_from_cr, priv_mov_from_psr, 0, 0,
+ 0, 0, 0, 0,
+ priv_mov_to_cr, priv_mov_to_psr, priv_itc_d, priv_itc_i,
+ 0, 0, 0, 0,
+ priv_ptc_e, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
};
-static IA64FAULT
-priv_handle_op(VCPU *vcpu, REGS *regs, int privlvl)
+static IA64FAULT priv_handle_op(VCPU * vcpu, REGS * regs, int privlvl)
{
IA64_BUNDLE bundle;
int slot;
@@ -512,85 +582,97 @@ priv_handle_op(VCPU *vcpu, REGS *regs, int privlvl)
INST64 inst;
PPEFCN pfunc;
unsigned long ipsr = regs->cr_ipsr;
- UINT64 iip = regs->cr_iip;
+ u64 iip = regs->cr_iip;
int x6;
-
+
// make a local copy of the bundle containing the privop
if (!vcpu_get_domain_bundle(vcpu, regs, iip, &bundle)) {
//return vcpu_force_data_miss(vcpu, regs->cr_iip);
return vcpu_force_inst_miss(vcpu, regs->cr_iip);
}
-
#if 0
- if (iip==0xa000000100001820) {
+ if (iip == 0xa000000100001820) {
static int firstpagefault = 1;
if (firstpagefault) {
- printf("*** First time to domain page fault!\n"); firstpagefault=0;
+ printf("*** First time to domain page fault!\n");
+ firstpagefault = 0;
}
}
#endif
if (privop_trace) {
static long i = 400;
//if (i > 0) printf("priv_handle_op: at 0x%lx\n",iip);
- if (i > 0) printf("priv_handle_op: privop trace at 0x%lx, itc=%lx, itm=%lx\n",
- iip,ia64_get_itc(),ia64_get_itm());
+ if (i > 0)
+ printf("priv_handle_op: privop trace at 0x%lx, "
+ "itc=%lx, itm=%lx\n",
+ iip, ia64_get_itc(), ia64_get_itm());
i--;
}
slot = ((struct ia64_psr *)&ipsr)->ri;
- if (!slot) inst.inst = (bundle.i64[0]>>5) & MASK_41;
+ if (!slot)
+ inst.inst = (bundle.i64[0] >> 5) & MASK_41;
else if (slot == 1)
- inst.inst = ((bundle.i64[0]>>46) | bundle.i64[1]<<18) & MASK_41;
- else if (slot == 2) inst.inst = (bundle.i64[1]>>23) & MASK_41;
- else printf("priv_handle_op: illegal slot: %d\n", slot);
+ inst.inst =
+ ((bundle.i64[0] >> 46) | bundle.i64[1] << 18) & MASK_41;
+ else if (slot == 2)
+ inst.inst = (bundle.i64[1] >> 23) & MASK_41;
+ else
+ printf("priv_handle_op: illegal slot: %d\n", slot);
slot_type = slot_types[bundle.template][slot];
if (priv_verbose) {
- printf("priv_handle_op: checking bundle at 0x%lx (op=0x%016lx) slot %d (type=%d)\n",
- iip, (UINT64)inst.inst, slot, slot_type);
+ printf("priv_handle_op: checking bundle at 0x%lx "
+ "(op=0x%016lx) slot %d (type=%d)\n",
+ iip, (u64) inst.inst, slot, slot_type);
}
if (slot_type == B && inst.generic.major == 0 && inst.B8.x6 == 0x0) {
// break instr for privified cover
- }
- else if (privlvl != 2) return (IA64_ILLOP_FAULT);
+ } else if (privlvl != 2)
+ return IA64_ILLOP_FAULT;
switch (slot_type) {
- case M:
+ case M:
if (inst.generic.major == 0) {
#if 0
if (inst.M29.x6 == 0 && inst.M29.x3 == 0) {
privcnt.cover++;
- return priv_cover(vcpu,inst);
+ return priv_cover(vcpu, inst);
}
#endif
- if (inst.M29.x3 != 0) break;
+ if (inst.M29.x3 != 0)
+ break;
if (inst.M30.x4 == 8 && inst.M30.x2 == 2) {
perfc_incrc(mov_to_ar_imm);
- return priv_mov_to_ar_imm(vcpu,inst);
+ return priv_mov_to_ar_imm(vcpu, inst);
}
if (inst.M44.x4 == 6) {
perfc_incrc(ssm);
- return priv_ssm(vcpu,inst);
+ return priv_ssm(vcpu, inst);
}
if (inst.M44.x4 == 7) {
perfc_incrc(rsm);
- return priv_rsm(vcpu,inst);
+ return priv_rsm(vcpu, inst);
}
break;
- }
- else if (inst.generic.major != 1) break;
+ } else if (inst.generic.major != 1)
+ break;
x6 = inst.M29.x6;
if (x6 == 0x2a) {
if (privify_en && inst.M29.r2 > 63 && inst.M29.ar3 < 8)
perfc_incrc(mov_from_ar); // privified mov from kr
else
perfc_incrc(mov_to_ar_reg);
- return priv_mov_to_ar_reg(vcpu,inst);
+ return priv_mov_to_ar_reg(vcpu, inst);
}
- if (inst.M29.x3 != 0) break;
- if (!(pfunc = Mpriv_funcs[x6])) break;
- if (x6 == 0x1e || x6 == 0x1f) { // tpa or tak are "special"
+ if (inst.M29.x3 != 0)
+ break;
+ if (!(pfunc = Mpriv_funcs[x6]))
+ break;
+ if (x6 == 0x1e || x6 == 0x1f) { // tpa or tak are "special"
if (privify_en && inst.M46.r3 > 63) {
- if (x6 == 0x1e) x6 = 0x1b;
- else x6 = 0x1a;
+ if (x6 == 0x1e)
+ x6 = 0x1b;
+ else
+ x6 = 0x1a;
}
}
if (privify_en && x6 == 52 && inst.M28.r3 > 63)
@@ -599,61 +681,66 @@ priv_handle_op(VCPU *vcpu, REGS *regs, int privlvl)
perfc_incrc(cpuid);
else
perfc_incra(misc_privop, x6);
- return (*pfunc)(vcpu,inst);
+ return (*pfunc) (vcpu, inst);
break;
- case B:
- if (inst.generic.major != 0) break;
+ case B:
+ if (inst.generic.major != 0)
+ break;
if (inst.B8.x6 == 0x08) {
IA64FAULT fault;
perfc_incrc(rfi);
- fault = priv_rfi(vcpu,inst);
- if (fault == IA64_NO_FAULT) fault = IA64_RFI_IN_PROGRESS;
+ fault = priv_rfi(vcpu, inst);
+ if (fault == IA64_NO_FAULT)
+ fault = IA64_RFI_IN_PROGRESS;
return fault;
}
if (inst.B8.x6 == 0x0c) {
perfc_incrc(bsw0);
- return priv_bsw0(vcpu,inst);
+ return priv_bsw0(vcpu, inst);
}
if (inst.B8.x6 == 0x0d) {
perfc_incrc(bsw1);
- return priv_bsw1(vcpu,inst);
+ return priv_bsw1(vcpu, inst);
}
if (inst.B8.x6 == 0x0) {
// break instr for privified cover
perfc_incrc(cover);
- return priv_cover(vcpu,inst);
+ return priv_cover(vcpu, inst);
}
break;
- case I:
- if (inst.generic.major != 0) break;
+ case I:
+ if (inst.generic.major != 0)
+ break;
#if 0
if (inst.I26.x6 == 0 && inst.I26.x3 == 0) {
perfc_incrc(cover);
- return priv_cover(vcpu,inst);
+ return priv_cover(vcpu, inst);
}
#endif
- if (inst.I26.x3 != 0) break; // I26.x3 == I27.x3
+ if (inst.I26.x3 != 0)
+ break; // I26.x3 == I27.x3
if (inst.I26.x6 == 0x2a) {
if (privify_en && inst.I26.r2 > 63 && inst.I26.ar3 < 8)
- perfc_incrc(mov_from_ar); // privified mov from kr
- else
+ perfc_incrc(mov_from_ar); // privified mov from kr
+ else
perfc_incrc(mov_to_ar_reg);
- return priv_mov_to_ar_reg(vcpu,inst);
+ return priv_mov_to_ar_reg(vcpu, inst);
}
if (inst.I27.x6 == 0x0a) {
perfc_incrc(mov_to_ar_imm);
- return priv_mov_to_ar_imm(vcpu,inst);
+ return priv_mov_to_ar_imm(vcpu, inst);
}
break;
- default:
+ default:
break;
}
- //printf("We who are about do die salute you\n");
- printf("priv_handle_op: can't handle privop at 0x%lx (op=0x%016lx) slot %d (type=%d), ipsr=0x%lx\n",
- iip, (UINT64)inst.inst, slot, slot_type, ipsr);
- //printf("vtop(0x%lx)==0x%lx\n", iip, tr_vtop(iip));
- //thread_mozambique("privop fault\n");
- return (IA64_ILLOP_FAULT);
+ //printf("We who are about do die salute you\n");
+ printf("priv_handle_op: can't handle privop at 0x%lx (op=0x%016lx) "
+ "slot %d (type=%d), ipsr=0x%lx\n",
+ iip, (u64) inst.inst, slot, slot_type, ipsr);
+ //printf("vtop(0x%lx)==0x%lx\n", iip, tr_vtop(iip));
+ //thread_mozambique("privop fault\n");
+ return IA64_ILLOP_FAULT;
}
/** Emulate a privileged operation.
@@ -666,142 +753,139 @@ priv_handle_op(VCPU *vcpu, REGS *regs, int privlvl)
* @param isrcode interrupt service routine code
* @return fault
*/
-IA64FAULT
-priv_emulate(VCPU *vcpu, REGS *regs, UINT64 isr)
+IA64FAULT priv_emulate(VCPU * vcpu, REGS * regs, u64 isr)
{
IA64FAULT fault;
- UINT64 ipsr = regs->cr_ipsr;
- UINT64 isrcode = (isr >> 4) & 0xf;
+ u64 ipsr = regs->cr_ipsr;
+ u64 isrcode = (isr >> 4) & 0xf;
int privlvl;
// handle privops masked as illops? and breaks (6)
if (isrcode != 1 && isrcode != 2 && isrcode != 0 && isrcode != 6) {
- printf("priv_emulate: isrcode != 0 or 1 or 2\n");
+ printf("priv_emulate: isrcode != 0 or 1 or 2\n");
printf("priv_emulate: returning ILLOP, not implemented!\n");
- while (1);
+ while (1) ;
return IA64_ILLOP_FAULT;
}
//if (isrcode != 1 && isrcode != 2) return 0;
privlvl = ia64_get_cpl(ipsr);
// its OK for a privified-cover to be executed in user-land
- fault = priv_handle_op(vcpu,regs,privlvl);
- if ((fault == IA64_NO_FAULT) || (fault == IA64_EXTINT_VECTOR)) { // success!!
+ fault = priv_handle_op(vcpu, regs, privlvl);
+ if ((fault == IA64_NO_FAULT) || (fault == IA64_EXTINT_VECTOR)) {
+ // success!!
// update iip/ipsr to point to the next instruction
(void)vcpu_increment_iip(vcpu);
}
if (fault == IA64_ILLOP_FAULT)
printf("priv_emulate: priv_handle_op fails, "
- "isr=0x%lx iip=%lx\n",isr, regs->cr_iip);
+ "isr=0x%lx iip=%lx\n", isr, regs->cr_iip);
return fault;
}
/* hyperprivops are generally executed in assembly (with physical psr.ic off)
* so this code is primarily used for debugging them */
-int
-ia64_hyperprivop(unsigned long iim, REGS *regs)
+int ia64_hyperprivop(unsigned long iim, REGS * regs)
{
struct vcpu *v = current;
- UINT64 val;
- UINT64 itir, ifa;
+ u64 val;
+ u64 itir, ifa;
if (!iim || iim > HYPERPRIVOP_MAX) {
panic_domain(regs, "bad hyperprivop: iim=%lx, iip=0x%lx\n",
- iim, regs->cr_iip);
+ iim, regs->cr_iip);
return 1;
}
perfc_incra(slow_hyperprivop, iim);
- switch(iim) {
- case HYPERPRIVOP_RFI:
- (void)vcpu_rfi(v);
+ switch (iim) {
+ case HYPERPRIVOP_RFI:
+ vcpu_rfi(v);
return 0; // don't update iip
- case HYPERPRIVOP_RSM_DT:
- (void)vcpu_reset_psr_dt(v);
+ case HYPERPRIVOP_RSM_DT:
+ vcpu_reset_psr_dt(v);
return 1;
- case HYPERPRIVOP_SSM_DT:
- (void)vcpu_set_psr_dt(v);
+ case HYPERPRIVOP_SSM_DT:
+ vcpu_set_psr_dt(v);
return 1;
- case HYPERPRIVOP_COVER:
- (void)vcpu_cover(v);
+ case HYPERPRIVOP_COVER:
+ vcpu_cover(v);
return 1;
- case HYPERPRIVOP_ITC_D:
- (void)vcpu_get_itir(v,&itir);
- (void)vcpu_get_ifa(v,&ifa);
- (void)vcpu_itc_d(v,regs->r8,itir,ifa);
+ case HYPERPRIVOP_ITC_D:
+ vcpu_get_itir(v, &itir);
+ vcpu_get_ifa(v, &ifa);
+ vcpu_itc_d(v, regs->r8, itir, ifa);
return 1;
- case HYPERPRIVOP_ITC_I:
- (void)vcpu_get_itir(v,&itir);
- (void)vcpu_get_ifa(v,&ifa);
- (void)vcpu_itc_i(v,regs->r8,itir,ifa);
+ case HYPERPRIVOP_ITC_I:
+ vcpu_get_itir(v, &itir);
+ vcpu_get_ifa(v, &ifa);
+ vcpu_itc_i(v, regs->r8, itir, ifa);
return 1;
- case HYPERPRIVOP_SSM_I:
- (void)vcpu_set_psr_i(v);
+ case HYPERPRIVOP_SSM_I:
+ vcpu_set_psr_i(v);
return 1;
- case HYPERPRIVOP_GET_IVR:
- (void)vcpu_get_ivr(v,&val);
+ case HYPERPRIVOP_GET_IVR:
+ vcpu_get_ivr(v, &val);
regs->r8 = val;
return 1;
- case HYPERPRIVOP_GET_TPR:
- (void)vcpu_get_tpr(v,&val);
+ case HYPERPRIVOP_GET_TPR:
+ vcpu_get_tpr(v, &val);
regs->r8 = val;
return 1;
- case HYPERPRIVOP_SET_TPR:
- (void)vcpu_set_tpr(v,regs->r8);
+ case HYPERPRIVOP_SET_TPR:
+ vcpu_set_tpr(v, regs->r8);
return 1;
- case HYPERPRIVOP_EOI:
- (void)vcpu_set_eoi(v,0L);
+ case HYPERPRIVOP_EOI:
+ vcpu_set_eoi(v, 0L);
return 1;
- case HYPERPRIVOP_SET_ITM:
- (void)vcpu_set_itm(v,regs->r8);
+ case HYPERPRIVOP_SET_ITM:
+ vcpu_set_itm(v, regs->r8);
return 1;
- case HYPERPRIVOP_THASH:
- (void)vcpu_thash(v,regs->r8,&val);
+ case HYPERPRIVOP_THASH:
+ vcpu_thash(v, regs->r8, &val);
regs->r8 = val;
return 1;
- case HYPERPRIVOP_PTC_GA:
- (void)vcpu_ptc_ga(v,regs->r8,(1L << ((regs->r9 & 0xfc) >> 2)));
+ case HYPERPRIVOP_PTC_GA:
+ vcpu_ptc_ga(v, regs->r8, (1L << ((regs->r9 & 0xfc) >> 2)));
return 1;
- case HYPERPRIVOP_ITR_D:
- (void)vcpu_get_itir(v,&itir);
- (void)vcpu_get_ifa(v,&ifa);
- (void)vcpu_itr_d(v,regs->r8,regs->r9,itir,ifa);
+ case HYPERPRIVOP_ITR_D:
+ vcpu_get_itir(v, &itir);
+ vcpu_get_ifa(v, &ifa);
+ vcpu_itr_d(v, regs->r8, regs->r9, itir, ifa);
return 1;
- case HYPERPRIVOP_GET_RR:
- (void)vcpu_get_rr(v,regs->r8,&val);
+ case HYPERPRIVOP_GET_RR:
+ vcpu_get_rr(v, regs->r8, &val);
regs->r8 = val;
return 1;
- case HYPERPRIVOP_SET_RR:
- (void)vcpu_set_rr(v,regs->r8,regs->r9);
+ case HYPERPRIVOP_SET_RR:
+ vcpu_set_rr(v, regs->r8, regs->r9);
return 1;
- case HYPERPRIVOP_SET_KR:
- (void)vcpu_set_ar(v,regs->r8,regs->r9);
+ case HYPERPRIVOP_SET_KR:
+ vcpu_set_ar(v, regs->r8, regs->r9);
return 1;
- case HYPERPRIVOP_FC:
- (void)vcpu_fc(v,regs->r8);
+ case HYPERPRIVOP_FC:
+ vcpu_fc(v, regs->r8);
return 1;
- case HYPERPRIVOP_GET_CPUID:
- (void)vcpu_get_cpuid(v,regs->r8,&val);
+ case HYPERPRIVOP_GET_CPUID:
+ vcpu_get_cpuid(v, regs->r8, &val);
regs->r8 = val;
return 1;
- case HYPERPRIVOP_GET_PMD:
- (void)vcpu_get_pmd(v,regs->r8,&val);
+ case HYPERPRIVOP_GET_PMD:
+ vcpu_get_pmd(v, regs->r8, &val);
regs->r8 = val;
return 1;
- case HYPERPRIVOP_GET_EFLAG:
- (void)vcpu_get_ar(v,24,&val);
+ case HYPERPRIVOP_GET_EFLAG:
+ vcpu_get_ar(v, 24, &val);
regs->r8 = val;
return 1;
- case HYPERPRIVOP_SET_EFLAG:
- (void)vcpu_set_ar(v,24,regs->r8);
+ case HYPERPRIVOP_SET_EFLAG:
+ vcpu_set_ar(v, 24, regs->r8);
return 1;
- case HYPERPRIVOP_RSM_BE:
- (void)vcpu_reset_psr_sm(v, IA64_PSR_BE);
+ case HYPERPRIVOP_RSM_BE:
+ vcpu_reset_psr_sm(v, IA64_PSR_BE);
return 1;
- case HYPERPRIVOP_GET_PSR:
- (void)vcpu_get_psr(v, &val);
+ case HYPERPRIVOP_GET_PSR:
+ vcpu_get_psr(v, &val);
regs->r8 = val;
return 1;
}
return 0;
}
-
-
diff --git a/xen/arch/ia64/xen/regionreg.c b/xen/arch/ia64/xen/regionreg.c
index 58c89201fb..2491c3ae62 100644
--- a/xen/arch/ia64/xen/regionreg.c
+++ b/xen/arch/ia64/xen/regionreg.c
@@ -17,7 +17,7 @@
#include <asm/vcpu.h>
/* Defined in xemasm.S */
-extern void ia64_new_rr7(unsigned long rid, void *shared_info, void *shared_arch_info, unsigned long shared_info_va, unsigned long p_vhpt);
+extern void ia64_new_rr7(unsigned long rid, void *shared_info, void *shared_arch_info, unsigned long shared_info_va, unsigned long va_vhpt);
/* RID virtualization mechanism is really simple: domains have less rid bits
than the host and the host rid space is shared among the domains. (Values
@@ -260,7 +260,7 @@ int set_one_rr(unsigned long rr, unsigned long val)
} else if (rreg == 7) {
ia64_new_rr7(vmMangleRID(newrrv.rrval),v->domain->shared_info,
v->arch.privregs, v->domain->arch.shared_info_va,
- __get_cpu_var(vhpt_paddr));
+ __va_ul(vcpu_vhpt_maddr(v)));
} else {
set_rr(rr,newrrv.rrval);
}
diff --git a/xen/arch/ia64/xen/tlb_track.c b/xen/arch/ia64/xen/tlb_track.c
new file mode 100644
index 0000000000..49a8a79768
--- /dev/null
+++ b/xen/arch/ia64/xen/tlb_track.c
@@ -0,0 +1,506 @@
+/******************************************************************************
+ * tlb_track.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 <asm/tlb_track.h>
+#include <asm/p2m_entry.h>
+#include <asm/vmx_mm_def.h> /* for IA64_RR_SHIFT */
+#include <asm/vmx_vcpu.h> /* for VRN7 */
+#include <asm/vcpu.h> /* for PSCB() */
+
+#define CONFIG_TLB_TRACK_DEBUG
+#ifdef CONFIG_TLB_TRACK_DEBUG
+# define tlb_track_printd(fmt, ...) \
+ printf("%s:%d " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#else
+# define tlb_track_printd(fmt, ...) do { } while (0)
+#endif
+
+static int
+tlb_track_allocate_entries(struct tlb_track* tlb_track)
+{
+ struct page_info* entry_page;
+ struct tlb_track_entry* track_entries;
+ unsigned int allocated;
+ unsigned long i;
+
+ BUG_ON(tlb_track->num_free > 0);
+ if (tlb_track->num_entries >= tlb_track->limit) {
+ DPRINTK("%s: num_entries %d limit %d\n",
+ __func__, tlb_track->num_entries, tlb_track->limit);
+ return -ENOMEM;
+ }
+ entry_page = alloc_domheap_page(NULL);
+ if (entry_page == NULL) {
+ DPRINTK("%s: domheap page failed. num_entries %d limit %d\n",
+ __func__, tlb_track->num_entries, tlb_track->limit);
+ return -ENOMEM;
+ }
+
+ list_add(&entry_page->list, &tlb_track->page_list);
+ track_entries = (struct tlb_track_entry*)page_to_virt(entry_page);
+ allocated = PAGE_SIZE / sizeof(track_entries[0]);
+ tlb_track->num_entries += allocated;
+ tlb_track->num_free += allocated;
+ for (i = 0; i < allocated; i++) {
+ list_add(&track_entries[i].list, &tlb_track->free_list);
+ // tlb_track_printd("track_entries[%ld] 0x%p\n", i, &track_entries[i]);
+ }
+ tlb_track_printd("allocated %d num_entries %d num_free %d\n",
+ allocated, tlb_track->num_entries, tlb_track->num_free);
+ return 0;
+}
+
+
+int
+tlb_track_create(struct domain* d)
+{
+ struct tlb_track* tlb_track = NULL;
+ struct page_info* hash_page = NULL;
+ unsigned int hash_size;
+ unsigned int hash_shift;
+ unsigned int i;
+
+ tlb_track = xmalloc(struct tlb_track);
+ if (tlb_track == NULL)
+ goto out;
+
+ hash_page = alloc_domheap_page(NULL);
+ if (hash_page == NULL)
+ goto out;
+
+ spin_lock_init(&tlb_track->free_list_lock);
+ INIT_LIST_HEAD(&tlb_track->free_list);
+ tlb_track->limit = TLB_TRACK_LIMIT_ENTRIES;
+ tlb_track->num_entries = 0;
+ tlb_track->num_free = 0;
+ INIT_LIST_HEAD(&tlb_track->page_list);
+ if (tlb_track_allocate_entries(tlb_track) < 0)
+ goto out;
+
+ spin_lock_init(&tlb_track->hash_lock);
+ /* XXX hash size optimization */
+ hash_size = PAGE_SIZE / sizeof(tlb_track->hash[0]);
+ for (hash_shift = 0; (1 << (hash_shift + 1)) < hash_size; hash_shift++)
+ /* nothing */;
+ tlb_track->hash_size = (1 << hash_shift);
+ tlb_track->hash_shift = hash_shift;
+ tlb_track->hash_mask = (1 << hash_shift) - 1;
+ tlb_track->hash = page_to_virt(hash_page);
+ for (i = 0; i < tlb_track->hash_size; i++)
+ INIT_LIST_HEAD(&tlb_track->hash[i]);
+
+ smp_mb(); /* make initialization visible before use. */
+ d->arch.tlb_track = tlb_track;
+ printk("%s:%d hash 0x%p hash_size %d \n",
+ __func__, __LINE__, tlb_track->hash, tlb_track->hash_size);
+
+ return 0;
+
+out:
+ if (hash_page != NULL)
+ free_domheap_page(hash_page);
+
+ if (tlb_track != NULL)
+ xfree(tlb_track);
+
+ return -ENOMEM;
+}
+
+void
+tlb_track_destroy(struct domain* d)
+{
+ struct tlb_track* tlb_track = d->arch.tlb_track;
+ struct page_info* page;
+ struct page_info* next;
+
+ spin_lock(&tlb_track->free_list_lock);
+ BUG_ON(tlb_track->num_free != tlb_track->num_entries);
+
+ list_for_each_entry_safe(page, next, &tlb_track->page_list, list) {
+ list_del(&page->list);
+ free_domheap_page(page);
+ }
+
+ free_domheap_page(virt_to_page(tlb_track->hash));
+ xfree(tlb_track);
+ // d->tlb_track = NULL;
+}
+
+static struct tlb_track_entry*
+tlb_track_get_entry(struct tlb_track* tlb_track)
+{
+ struct tlb_track_entry* entry = NULL;
+ spin_lock(&tlb_track->free_list_lock);
+ if (tlb_track->num_free == 0)
+ (void)tlb_track_allocate_entries(tlb_track);
+
+ if (tlb_track->num_free > 0) {
+ BUG_ON(list_empty(&tlb_track->free_list));
+ entry = list_entry(tlb_track->free_list.next,
+ struct tlb_track_entry, list);
+ tlb_track->num_free--;
+ list_del(&entry->list);
+ }
+ spin_unlock(&tlb_track->free_list_lock);
+ return entry;
+}
+
+void
+tlb_track_free_entry(struct tlb_track* tlb_track,
+ struct tlb_track_entry* entry)
+{
+ spin_lock(&tlb_track->free_list_lock);
+ list_add(&entry->list, &tlb_track->free_list);
+ tlb_track->num_free++;
+ spin_unlock(&tlb_track->free_list_lock);
+}
+
+
+#include <linux/hash.h>
+/* XXX hash function. */
+static struct list_head*
+tlb_track_hash_head(struct tlb_track* tlb_track, volatile pte_t* ptep)
+{
+ unsigned long hash = hash_long((unsigned long)ptep, tlb_track->hash_shift);
+ BUG_ON(hash >= tlb_track->hash_size);
+ BUG_ON((hash & tlb_track->hash_mask) != hash);
+ return &tlb_track->hash[hash];
+}
+
+static int
+tlb_track_pte_zapped(pte_t old_pte, pte_t ret_pte)
+{
+ if (pte_pfn(old_pte) != pte_pfn(ret_pte) ||
+ (pte_val(old_pte) & ~(_PFN_MASK | _PAGE_TLB_TRACK_MASK)) !=
+ (pte_val(ret_pte) & ~(_PFN_MASK | _PAGE_TLB_TRACK_MASK))) {
+ /* Other thread zapped the p2m entry. */
+ return 1;
+ }
+ return 0;
+}
+
+static TLB_TRACK_RET_T
+tlb_track_insert_or_dirty(struct tlb_track* tlb_track, struct mm_struct* mm,
+ volatile pte_t* ptep, pte_t old_pte,
+ unsigned long vaddr, unsigned long rid)
+{
+ unsigned long mfn = pte_pfn(old_pte);
+ struct list_head* head = tlb_track_hash_head(tlb_track, ptep);
+ struct tlb_track_entry* entry;
+ struct tlb_track_entry* new_entry = NULL;
+ unsigned long bit_to_be_set = _PAGE_TLB_INSERTED;
+ pte_t new_pte;
+ pte_t ret_pte;
+
+ struct vcpu* v = current;
+ TLB_TRACK_RET_T ret = TLB_TRACK_NOT_FOUND;
+
+#if 0 /* this is done at vcpu_tlb_track_insert_or_dirty() */
+ perfc_incrc(tlb_track_iod);
+ if (!pte_tlb_tracking(old_pte)) {
+ perfc_incrc(tlb_track_iod_not_tracked);
+ return TLB_TRACK_NOT_TRACKED;
+ }
+#endif
+ if (pte_tlb_inserted_many(old_pte)) {
+ perfc_incrc(tlb_track_iod_tracked_many);
+ return TLB_TRACK_MANY;
+ }
+
+ /* vaddr must be normalized so that it is in vrn7 and page aligned. */
+ BUG_ON((vaddr >> IA64_RR_SHIFT) != VRN7);
+ BUG_ON((vaddr & ~PAGE_MASK) != 0);
+#if 0
+ tlb_track_printd("\n"
+ "\tmfn 0x%016lx\n"
+ "\told_pte 0x%016lx ptep 0x%p\n"
+ "\tptep_val 0x%016lx vaddr 0x%016lx rid %ld\n"
+ "\ttlb_track 0x%p head 0x%p\n",
+ mfn,
+ pte_val(old_pte), ptep, pte_val(*ptep),
+ vaddr, rid,
+ tlb_track, head);
+#endif
+
+ again:
+ /*
+ * zapping side may zap the p2m entry and then remove tlb track entry
+ * non-atomically. We may see the stale tlb track entry here.
+ * p2m_entry_retry() handles such a case.
+ * Or other thread may zap the p2m entry and remove tlb track entry
+ * and inserted new tlb track entry.
+ */
+ spin_lock(&tlb_track->hash_lock);
+ list_for_each_entry(entry, head, list) {
+ if (entry->ptep != ptep)
+ continue;
+
+ if (pte_pfn(entry->pte_val) == mfn) {
+ // tlb_track_entry_printf(entry);
+ if (entry->vaddr == vaddr && entry->rid == rid) {
+ // tlb_track_printd("TLB_TRACK_FOUND\n");
+ ret = TLB_TRACK_FOUND;
+ perfc_incrc(tlb_track_iod_found);
+#ifdef CONFIG_TLB_TRACK_CNT
+ entry->cnt++;
+ if (entry->cnt > TLB_TRACK_CNT_FORCE_MANY) {
+ /*
+ * heuristics:
+ * If a page is used to transfer data by dev channel,
+ * it would be unmapped with small amount access
+ * (once or twice tlb insert) after real device
+ * I/O completion. It would be short period.
+ * However this page seems to be accessed many times.
+ * We guess that this page is used I/O ring
+ * so that tracking this entry might be useless.
+ */
+ // tlb_track_entry_printf(entry);
+ // tlb_track_printd("cnt = %ld\n", entry->cnt);
+ perfc_incrc(tlb_track_iod_force_many);
+ goto force_many;
+ }
+#endif
+ goto found;
+ } else {
+#ifdef CONFIG_TLB_TRACK_CNT
+ force_many:
+#endif
+ if (!pte_tlb_inserted(old_pte)) {
+ printk("%s:%d racy update\n", __func__, __LINE__);
+ old_pte = __pte(pte_val(old_pte) | _PAGE_TLB_INSERTED);
+ }
+ new_pte = __pte(pte_val(old_pte) | _PAGE_TLB_INSERTED_MANY);
+ ret_pte = ptep_cmpxchg_rel(mm, vaddr, ptep, old_pte, new_pte);
+ if (pte_val(ret_pte) != pte_val(old_pte)) {
+ // tlb_track_printd("TLB_TRACK_AGAIN\n");
+ ret = TLB_TRACK_AGAIN;
+ perfc_incrc(tlb_track_iod_again);
+ } else {
+ // tlb_track_printd("TLB_TRACK_MANY del entry 0x%p\n",
+ // entry);
+ ret = TLB_TRACK_MANY;
+ list_del(&entry->list);
+ // tlb_track_entry_printf(entry);
+ perfc_incrc(tlb_track_iod_tracked_many_del);
+ }
+ goto out;
+ }
+ }
+
+ /*
+ * Other thread changed the p2m entry and removed and inserted new
+ * tlb tracn entry after we get old_pte, but before we get
+ * spinlock.
+ */
+ // tlb_track_printd("TLB_TRACK_AGAIN\n");
+ ret = TLB_TRACK_AGAIN;
+ perfc_incrc(tlb_track_iod_again);
+ goto out;
+ }
+
+ entry = NULL; // prevent freeing entry.
+ if (pte_tlb_inserted(old_pte)) {
+ /* Other thread else removed the tlb_track_entry after we got old_pte
+ before we got spin lock. */
+ ret = TLB_TRACK_AGAIN;
+ perfc_incrc(tlb_track_iod_again);
+ goto out;
+ }
+ if (new_entry == NULL && bit_to_be_set == _PAGE_TLB_INSERTED) {
+ spin_unlock(&tlb_track->hash_lock);
+ new_entry = tlb_track_get_entry(tlb_track);
+ if (new_entry == NULL) {
+ tlb_track_printd("get_entry failed\n");
+ /* entry can't be allocated.
+ fall down into full flush mode. */
+ bit_to_be_set |= _PAGE_TLB_INSERTED_MANY;
+ perfc_incrc(tlb_track_iod_new_failed);
+ }
+ // tlb_track_printd("new_entry 0x%p\n", new_entry);
+ perfc_incrc(tlb_track_iod_new_entry);
+ goto again;
+ }
+
+ BUG_ON(pte_tlb_inserted_many(old_pte));
+ new_pte = __pte(pte_val(old_pte) | bit_to_be_set);
+ ret_pte = ptep_cmpxchg_rel(mm, vaddr, ptep, old_pte, new_pte);
+ if (pte_val(old_pte) != pte_val(ret_pte)) {
+ if (tlb_track_pte_zapped(old_pte, ret_pte)) {
+ // tlb_track_printd("zapped TLB_TRACK_AGAIN\n");
+ ret = TLB_TRACK_AGAIN;
+ perfc_incrc(tlb_track_iod_again);
+ goto out;
+ }
+
+ /* Other thread set _PAGE_TLB_INSERTED and/or _PAGE_TLB_INSERTED_MANY */
+ if (pte_tlb_inserted_many(ret_pte)) {
+ /* Other thread already set _PAGE_TLB_INSERTED_MANY and
+ removed the entry. */
+ // tlb_track_printd("iserted TLB_TRACK_MANY\n");
+ BUG_ON(!pte_tlb_inserted(ret_pte));
+ ret = TLB_TRACK_MANY;
+ perfc_incrc(tlb_track_iod_new_many);
+ goto out;
+ }
+ BUG_ON(pte_tlb_inserted(ret_pte));
+ BUG();
+ }
+ if (new_entry) {
+ // tlb_track_printd("iserting new_entry 0x%p\n", new_entry);
+ entry = new_entry;
+ new_entry = NULL;
+
+ entry->ptep = ptep;
+ entry->pte_val = old_pte;
+ entry->vaddr = vaddr;
+ entry->rid = rid;
+ cpus_clear(entry->pcpu_dirty_mask);
+ vcpus_clear(entry->vcpu_dirty_mask);
+ list_add(&entry->list, head);
+
+#ifdef CONFIG_TLB_TRACK_CNT
+ entry->cnt = 0;
+#endif
+ perfc_incrc(tlb_track_iod_insert);
+ // tlb_track_entry_printf(entry);
+ } else {
+ goto out;
+ }
+
+ found:
+ BUG_ON(v->processor >= NR_CPUS);
+ cpu_set(v->processor, entry->pcpu_dirty_mask);
+ BUG_ON(v->vcpu_id >= NR_CPUS);
+ vcpu_set(v->vcpu_id, entry->vcpu_dirty_mask);
+ perfc_incrc(tlb_track_iod_dirtied);
+
+ out:
+ spin_unlock(&tlb_track->hash_lock);
+ if (ret == TLB_TRACK_MANY && entry != NULL)
+ tlb_track_free_entry(tlb_track, entry);
+ if (new_entry != NULL)
+ tlb_track_free_entry(tlb_track, new_entry);
+ return ret;
+}
+
+void
+__vcpu_tlb_track_insert_or_dirty(struct vcpu *vcpu, unsigned long vaddr,
+ struct p2m_entry* entry)
+{
+ unsigned long vrn = vaddr >> IA64_RR_SHIFT;
+ unsigned long rid = PSCB(vcpu, rrs[vrn]);
+ TLB_TRACK_RET_T ret;
+
+ /* normalize vrn7
+ When linux dom0 case, vrn7 is the most common case. */
+ vaddr |= VRN7 << VRN_SHIFT;
+ vaddr &= PAGE_MASK;
+ ret = tlb_track_insert_or_dirty(vcpu->domain->arch.tlb_track,
+ &vcpu->domain->arch.mm,
+ entry->ptep, entry->used,
+ vaddr, rid);
+ if (ret == TLB_TRACK_AGAIN)
+ p2m_entry_set_retry(entry);
+}
+
+TLB_TRACK_RET_T
+tlb_track_search_and_remove(struct tlb_track* tlb_track,
+ volatile pte_t* ptep, pte_t old_pte,
+ struct tlb_track_entry** entryp)
+{
+ unsigned long mfn = pte_pfn(old_pte);
+ struct list_head* head = tlb_track_hash_head(tlb_track, ptep);
+ struct tlb_track_entry* entry;
+
+ perfc_incrc(tlb_track_sar);
+ if (!pte_tlb_tracking(old_pte)) {
+ perfc_incrc(tlb_track_sar_not_tracked);
+ return TLB_TRACK_NOT_TRACKED;
+ }
+ if (!pte_tlb_inserted(old_pte)) {
+ BUG_ON(pte_tlb_inserted_many(old_pte));
+ perfc_incrc(tlb_track_sar_not_found);
+ return TLB_TRACK_NOT_FOUND;
+ }
+ if (pte_tlb_inserted_many(old_pte)) {
+ BUG_ON(!pte_tlb_inserted(old_pte));
+ perfc_incrc(tlb_track_sar_many);
+ return TLB_TRACK_MANY;
+ }
+
+ spin_lock(&tlb_track->hash_lock);
+ list_for_each_entry(entry, head, list) {
+ if (entry->ptep != ptep)
+ continue;
+
+ if (pte_pfn(entry->pte_val) == mfn) {
+ list_del(&entry->list);
+ spin_unlock(&tlb_track->hash_lock);
+ *entryp = entry;
+ perfc_incrc(tlb_track_sar_found);
+ // tlb_track_entry_printf(entry);
+#ifdef CONFIG_TLB_TRACK_CNT
+ // tlb_track_printd("cnt = %ld\n", entry->cnt);
+#endif
+ return TLB_TRACK_FOUND;
+ }
+ BUG();
+ }
+ BUG();
+ spin_unlock(&tlb_track->hash_lock);
+ return TLB_TRACK_NOT_TRACKED;
+}
+
+/* for debug */
+void
+__tlb_track_entry_printf(const char* func, int line,
+ const struct tlb_track_entry* entry)
+{
+ char pcpumask_buf[NR_CPUS + 1];
+ char vcpumask_buf[MAX_VIRT_CPUS + 1];
+ cpumask_scnprintf(pcpumask_buf, sizeof(pcpumask_buf),
+ entry->pcpu_dirty_mask);
+ vcpumask_scnprintf(vcpumask_buf, sizeof(vcpumask_buf),
+ entry->vcpu_dirty_mask);
+ printk("%s:%d\n"
+ "\tmfn 0x%016lx\n"
+ "\told_pte 0x%016lx ptep 0x%p\n"
+ "\tpte_val 0x%016lx vaddr 0x%016lx rid %ld\n"
+ "\tpcpu_dirty_mask %s vcpu_dirty_mask %s\n"
+ "\tentry 0x%p\n",
+ func, line,
+ pte_pfn(entry->pte_val),
+ pte_val(entry->pte_val), entry->ptep, pte_val(*entry->ptep),
+ entry->vaddr, entry->rid,
+ pcpumask_buf, vcpumask_buf,
+ entry);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c
index cab06b2576..7ead59ca7f 100644
--- a/xen/arch/ia64/xen/vcpu.c
+++ b/xen/arch/ia64/xen/vcpu.c
@@ -24,29 +24,35 @@
#include <asm/bundle.h>
#include <asm/privop_stat.h>
#include <asm/uaccess.h>
+#include <asm/p2m_entry.h>
+#include <asm/tlb_track.h>
/* FIXME: where these declarations should be there ? */
-extern void getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs);
-extern void setreg(unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs);
-extern void getfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs);
+extern void getreg(unsigned long regnum, unsigned long *val, int *nat,
+ struct pt_regs *regs);
+extern void setreg(unsigned long regnum, unsigned long val, int nat,
+ struct pt_regs *regs);
+extern void getfpreg(unsigned long regnum, struct ia64_fpreg *fpval,
+ struct pt_regs *regs);
-extern void setfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs);
+extern void setfpreg(unsigned long regnum, struct ia64_fpreg *fpval,
+ struct pt_regs *regs);
-typedef union {
+typedef union {
struct ia64_psr ia64_psr;
unsigned long i64;
} PSR;
// this def for vcpu_regs won't work if kernel stack is present
-//#define vcpu_regs(vcpu) ((struct pt_regs *) vcpu->arch.regs
+//#define vcpu_regs(vcpu) ((struct pt_regs *) vcpu->arch.regs
-#define TRUE 1
-#define FALSE 0
+#define TRUE 1
+#define FALSE 0
#define IA64_PTA_SZ_BIT 2
#define IA64_PTA_VF_BIT 8
#define IA64_PTA_BASE_BIT 15
#define IA64_PTA_LFMT (1UL << IA64_PTA_VF_BIT)
-#define IA64_PTA_SZ(x) (x##UL << IA64_PTA_SZ_BIT)
+#define IA64_PTA_SZ(x) (x##UL << IA64_PTA_SZ_BIT)
unsigned long vcpu_verbose = 0;
@@ -54,23 +60,23 @@ unsigned long vcpu_verbose = 0;
VCPU general register access routines
**************************************************************************/
#ifdef XEN
-UINT64
-vcpu_get_gr(VCPU *vcpu, unsigned long reg)
+u64 vcpu_get_gr(VCPU * vcpu, unsigned long reg)
{
REGS *regs = vcpu_regs(vcpu);
- UINT64 val;
+ u64 val;
- if (!reg) return 0;
- getreg(reg,&val,0,regs); // FIXME: handle NATs later
+ if (!reg)
+ return 0;
+ getreg(reg, &val, 0, regs); // FIXME: handle NATs later
return val;
}
-IA64FAULT
-vcpu_get_gr_nat(VCPU *vcpu, unsigned long reg, UINT64 *val)
+
+IA64FAULT vcpu_get_gr_nat(VCPU * vcpu, unsigned long reg, u64 * val)
{
REGS *regs = vcpu_regs(vcpu);
int nat;
- getreg(reg,val,&nat,regs); // FIXME: handle NATs later
+ getreg(reg, val, &nat, regs); // FIXME: handle NATs later
if (nat)
return IA64_NAT_CONSUMPTION_VECTOR;
return 0;
@@ -79,32 +85,33 @@ vcpu_get_gr_nat(VCPU *vcpu, unsigned long reg, UINT64 *val)
// returns:
// IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
// IA64_NO_FAULT otherwise
-IA64FAULT
-vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value, int nat)
+IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value, int nat)
{
REGS *regs = vcpu_regs(vcpu);
long sof = (regs->cr_ifs) & 0x7f;
- if (!reg) return IA64_ILLOP_FAULT;
- if (reg >= sof + 32) return IA64_ILLOP_FAULT;
- setreg(reg,value,nat,regs); // FIXME: handle NATs later
+ if (!reg)
+ return IA64_ILLOP_FAULT;
+ if (reg >= sof + 32)
+ return IA64_ILLOP_FAULT;
+ setreg(reg, value, nat, regs); // FIXME: handle NATs later
return IA64_NO_FAULT;
}
IA64FAULT
-vcpu_get_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
+vcpu_get_fpreg(VCPU * vcpu, unsigned long reg, struct ia64_fpreg * val)
{
REGS *regs = vcpu_regs(vcpu);
- getfpreg(reg,val,regs); // FIXME: handle NATs later
+ getfpreg(reg, val, regs); // FIXME: handle NATs later
return IA64_NO_FAULT;
}
IA64FAULT
-vcpu_set_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
+vcpu_set_fpreg(VCPU * vcpu, unsigned long reg, struct ia64_fpreg * val)
{
REGS *regs = vcpu_regs(vcpu);
- if(reg > 1)
- setfpreg(reg,val,regs); // FIXME: handle NATs later
+ if (reg > 1)
+ setfpreg(reg, val, regs); // FIXME: handle NATs later
return IA64_NO_FAULT;
}
@@ -112,38 +119,39 @@ vcpu_set_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val)
// returns:
// IA64_ILLOP_FAULT if the register would cause an Illegal Operation fault
// IA64_NO_FAULT otherwise
-IA64FAULT
-vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value)
+IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value)
{
REGS *regs = vcpu_regs(vcpu);
long sof = (regs->cr_ifs) & 0x7f;
- if (!reg) return IA64_ILLOP_FAULT;
- if (reg >= sof + 32) return IA64_ILLOP_FAULT;
- setreg(reg,value,0,regs); // FIXME: handle NATs later
+ if (!reg)
+ return IA64_ILLOP_FAULT;
+ if (reg >= sof + 32)
+ return IA64_ILLOP_FAULT;
+ setreg(reg, value, 0, regs); // FIXME: handle NATs later
return IA64_NO_FAULT;
}
#endif
-void vcpu_init_regs (struct vcpu *v)
+void vcpu_init_regs(struct vcpu *v)
{
struct pt_regs *regs;
- regs = vcpu_regs (v);
+ regs = vcpu_regs(v);
if (VMX_DOMAIN(v)) {
/* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */
/* Need to be expanded as macro */
regs->cr_ipsr = 0x501008826008;
} else {
regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
- | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
+ | IA64_PSR_BITS_TO_SET | IA64_PSR_BN;
regs->cr_ipsr &= ~(IA64_PSR_BITS_TO_CLEAR
| IA64_PSR_RI | IA64_PSR_IS);
// domain runs at PL2
regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT;
}
- regs->cr_ifs = 1UL << 63; /* or clear? */
+ regs->cr_ifs = 1UL << 63; /* or clear? */
regs->ar_fpsr = FPSR_DEFAULT;
if (VMX_DOMAIN(v)) {
@@ -153,13 +161,13 @@ void vcpu_init_regs (struct vcpu *v)
VCPU(v, dcr) = 0;
} else {
init_all_rr(v);
- regs->ar_rsc |= (2 << 2); /* force PL2/3 */
+ regs->ar_rsc |= (2 << 2); /* force PL2/3 */
VCPU(v, banknum) = 1;
VCPU(v, metaphysical_mode) = 1;
VCPU(v, interrupt_mask_addr) =
- (unsigned char *)v->domain->arch.shared_info_va +
- INT_ENABLE_OFFSET(v);
- VCPU(v, itv) = (1 << 16); /* timer vector masked */
+ (unsigned char *)v->domain->arch.shared_info_va +
+ INT_ENABLE_OFFSET(v);
+ VCPU(v, itv) = (1 << 16); /* timer vector masked */
}
v->arch.domain_itm_last = -1L;
@@ -169,7 +177,7 @@ void vcpu_init_regs (struct vcpu *v)
VCPU privileged application register access routines
**************************************************************************/
-void vcpu_load_kernel_regs(VCPU *vcpu)
+void vcpu_load_kernel_regs(VCPU * vcpu)
{
ia64_set_kr(0, VCPU(vcpu, krs[0]));
ia64_set_kr(1, VCPU(vcpu, krs[1]));
@@ -184,26 +192,33 @@ void vcpu_load_kernel_regs(VCPU *vcpu)
/* GCC 4.0.2 seems not to be able to suppress this call!. */
#define ia64_setreg_unknown_kr() return IA64_ILLOP_FAULT
-IA64FAULT vcpu_set_ar(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vcpu_set_ar(VCPU * vcpu, u64 reg, u64 val)
{
- if (reg == 44) return (vcpu_set_itc(vcpu,val));
- else if (reg == 27) return (IA64_ILLOP_FAULT);
+ if (reg == 44)
+ return vcpu_set_itc(vcpu, val);
+ else if (reg == 27)
+ return IA64_ILLOP_FAULT;
else if (reg == 24)
- printf("warning: setting ar.eflg is a no-op; no IA-32 support\n");
- else if (reg > 7) return (IA64_ILLOP_FAULT);
+ printf("warning: setting ar.eflg is a no-op; no IA-32 "
+ "support\n");
+ else if (reg > 7)
+ return IA64_ILLOP_FAULT;
else {
- PSCB(vcpu,krs[reg]) = val;
- ia64_set_kr(reg,val);
+ PSCB(vcpu, krs[reg]) = val;
+ ia64_set_kr(reg, val);
}
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_ar(VCPU *vcpu, UINT64 reg, UINT64 *val)
+IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 reg, u64 * val)
{
if (reg == 24)
- printf("warning: getting ar.eflg is a no-op; no IA-32 support\n");
- else if (reg > 7) return (IA64_ILLOP_FAULT);
- else *val = PSCB(vcpu,krs[reg]);
+ printf("warning: getting ar.eflg is a no-op; no IA-32 "
+ "support\n");
+ else if (reg > 7)
+ return IA64_ILLOP_FAULT;
+ else
+ *val = PSCB(vcpu, krs[reg]);
return IA64_NO_FAULT;
}
@@ -211,24 +226,25 @@ IA64FAULT vcpu_get_ar(VCPU *vcpu, UINT64 reg, UINT64 *val)
VCPU processor status register access routines
**************************************************************************/
-void vcpu_set_metaphysical_mode(VCPU *vcpu, BOOLEAN newmode)
+void vcpu_set_metaphysical_mode(VCPU * vcpu, BOOLEAN newmode)
{
/* only do something if mode changes */
- if (!!newmode ^ !!PSCB(vcpu,metaphysical_mode)) {
- PSCB(vcpu,metaphysical_mode) = newmode;
- if (newmode) set_metaphysical_rr0();
- else if (PSCB(vcpu,rrs[0]) != -1)
- set_one_rr(0, PSCB(vcpu,rrs[0]));
+ if (!!newmode ^ !!PSCB(vcpu, metaphysical_mode)) {
+ PSCB(vcpu, metaphysical_mode) = newmode;
+ if (newmode)
+ set_metaphysical_rr0();
+ else if (PSCB(vcpu, rrs[0]) != -1)
+ set_one_rr(0, PSCB(vcpu, rrs[0]));
}
}
-IA64FAULT vcpu_reset_psr_dt(VCPU *vcpu)
+IA64FAULT vcpu_reset_psr_dt(VCPU * vcpu)
{
- vcpu_set_metaphysical_mode(vcpu,TRUE);
+ vcpu_set_metaphysical_mode(vcpu, TRUE);
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
+IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24)
{
struct ia64_psr psr, imm, *ipsr;
REGS *regs = vcpu_regs(vcpu);
@@ -236,72 +252,89 @@ IA64FAULT vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24)
//PRIVOP_COUNT_ADDR(regs,_RSM);
// TODO: All of these bits need to be virtualized
// TODO: Only allowed for current vcpu
- __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
+ __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
ipsr = (struct ia64_psr *)&regs->cr_ipsr;
imm = *(struct ia64_psr *)&imm24;
// interrupt flag
if (imm.i)
- vcpu->vcpu_info->evtchn_upcall_mask = 1;
- if (imm.ic) PSCB(vcpu,interrupt_collection_enabled) = 0;
+ vcpu->vcpu_info->evtchn_upcall_mask = 1;
+ if (imm.ic)
+ PSCB(vcpu, interrupt_collection_enabled) = 0;
// interrupt collection flag
//if (imm.ic) PSCB(vcpu,interrupt_delivery_enabled) = 0;
// just handle psr.up and psr.pp for now
- if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP
- | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT
- | IA64_PSR_DFL | IA64_PSR_DFH))
- return (IA64_ILLOP_FAULT);
- if (imm.dfh) ipsr->dfh = 0;
- if (imm.dfl) ipsr->dfl = 0;
+ if (imm24 & ~(IA64_PSR_BE | IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP |
+ IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT |
+ IA64_PSR_DFL | IA64_PSR_DFH))
+ return IA64_ILLOP_FAULT;
+ if (imm.dfh)
+ ipsr->dfh = 0;
+ if (imm.dfl)
+ ipsr->dfl = 0;
if (imm.pp) {
ipsr->pp = 1;
psr.pp = 1; // priv perf ctrs always enabled
- PSCB(vcpu,vpsr_pp) = 0; // but fool the domain if it gets psr
+ PSCB(vcpu, vpsr_pp) = 0; // but fool the domain if it gets psr
}
- if (imm.up) { ipsr->up = 0; psr.up = 0; }
- if (imm.sp) { ipsr->sp = 0; psr.sp = 0; }
- if (imm.be) ipsr->be = 0;
- if (imm.dt) vcpu_set_metaphysical_mode(vcpu,TRUE);
- __asm__ __volatile (";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
+ if (imm.up) {
+ ipsr->up = 0;
+ psr.up = 0;
+ }
+ if (imm.sp) {
+ ipsr->sp = 0;
+ psr.sp = 0;
+ }
+ if (imm.be)
+ ipsr->be = 0;
+ if (imm.dt)
+ vcpu_set_metaphysical_mode(vcpu, TRUE);
+ __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
return IA64_NO_FAULT;
}
-
-IA64FAULT vcpu_set_psr_dt(VCPU *vcpu)
+IA64FAULT vcpu_set_psr_dt(VCPU * vcpu)
{
- vcpu_set_metaphysical_mode(vcpu,FALSE);
+ vcpu_set_metaphysical_mode(vcpu, FALSE);
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_psr_i(VCPU *vcpu)
+IA64FAULT vcpu_set_psr_i(VCPU * vcpu)
{
vcpu->vcpu_info->evtchn_upcall_mask = 0;
- PSCB(vcpu,interrupt_collection_enabled) = 1;
+ PSCB(vcpu, interrupt_collection_enabled) = 1;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
+IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24)
{
struct ia64_psr psr, imm, *ipsr;
REGS *regs = vcpu_regs(vcpu);
- UINT64 mask, enabling_interrupts = 0;
+ u64 mask, enabling_interrupts = 0;
//PRIVOP_COUNT_ADDR(regs,_SSM);
// TODO: All of these bits need to be virtualized
- __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
+ __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
imm = *(struct ia64_psr *)&imm24;
ipsr = (struct ia64_psr *)&regs->cr_ipsr;
// just handle psr.sp,pp and psr.i,ic (and user mask) for now
- mask = IA64_PSR_PP|IA64_PSR_SP|IA64_PSR_I|IA64_PSR_IC|IA64_PSR_UM |
- IA64_PSR_DT|IA64_PSR_DFL|IA64_PSR_DFH;
- if (imm24 & ~mask) return (IA64_ILLOP_FAULT);
- if (imm.dfh) ipsr->dfh = 1;
- if (imm.dfl) ipsr->dfl = 1;
+ mask =
+ IA64_PSR_PP | IA64_PSR_SP | IA64_PSR_I | IA64_PSR_IC | IA64_PSR_UM |
+ IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH;
+ if (imm24 & ~mask)
+ return IA64_ILLOP_FAULT;
+ if (imm.dfh)
+ ipsr->dfh = 1;
+ if (imm.dfl)
+ ipsr->dfl = 1;
if (imm.pp) {
ipsr->pp = 1;
psr.pp = 1;
- PSCB(vcpu,vpsr_pp) = 1;
+ PSCB(vcpu, vpsr_pp) = 1;
+ }
+ if (imm.sp) {
+ ipsr->sp = 1;
+ psr.sp = 1;
}
- if (imm.sp) { ipsr->sp = 1; psr.sp = 1; }
if (imm.i) {
if (vcpu->vcpu_info->evtchn_upcall_mask) {
//printf("vcpu_set_psr_sm: psr.ic 0->1\n");
@@ -309,114 +342,169 @@ IA64FAULT vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24)
}
vcpu->vcpu_info->evtchn_upcall_mask = 0;
}
- if (imm.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
+ if (imm.ic)
+ PSCB(vcpu, interrupt_collection_enabled) = 1;
// TODO: do this faster
- if (imm.mfl) { ipsr->mfl = 1; psr.mfl = 1; }
- if (imm.mfh) { ipsr->mfh = 1; psr.mfh = 1; }
- if (imm.ac) { ipsr->ac = 1; psr.ac = 1; }
- if (imm.up) { ipsr->up = 1; psr.up = 1; }
+ if (imm.mfl) {
+ ipsr->mfl = 1;
+ psr.mfl = 1;
+ }
+ if (imm.mfh) {
+ ipsr->mfh = 1;
+ psr.mfh = 1;
+ }
+ if (imm.ac) {
+ ipsr->ac = 1;
+ psr.ac = 1;
+ }
+ if (imm.up) {
+ ipsr->up = 1;
+ psr.up = 1;
+ }
if (imm.be) {
printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
- if (imm.dt) vcpu_set_metaphysical_mode(vcpu,FALSE);
- __asm__ __volatile (";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
+ if (imm.dt)
+ vcpu_set_metaphysical_mode(vcpu, FALSE);
+ __asm__ __volatile(";; mov psr.l=%0;; srlz.d"::"r"(psr):"memory");
if (enabling_interrupts &&
- vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
- PSCB(vcpu,pending_interruption) = 1;
+ vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
+ PSCB(vcpu, pending_interruption) = 1;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_psr_l(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val)
{
struct ia64_psr psr, newpsr, *ipsr;
REGS *regs = vcpu_regs(vcpu);
- UINT64 enabling_interrupts = 0;
+ u64 enabling_interrupts = 0;
// TODO: All of these bits need to be virtualized
- __asm__ __volatile ("mov %0=psr;;" : "=r"(psr) :: "memory");
+ __asm__ __volatile("mov %0=psr;;":"=r"(psr)::"memory");
newpsr = *(struct ia64_psr *)&val;
ipsr = (struct ia64_psr *)&regs->cr_ipsr;
// just handle psr.up and psr.pp for now
- //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP)) return (IA64_ILLOP_FAULT);
+ //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP))
+ // return IA64_ILLOP_FAULT;
// however trying to set other bits can't be an error as it is in ssm
- if (newpsr.dfh) ipsr->dfh = 1;
- if (newpsr.dfl) ipsr->dfl = 1;
+ if (newpsr.dfh)
+ ipsr->dfh = 1;
+ if (newpsr.dfl)
+ ipsr->dfl = 1;
if (newpsr.pp) {
- ipsr->pp = 1; psr.pp = 1;
- PSCB(vcpu,vpsr_pp) = 1;
+ ipsr->pp = 1;
+ psr.pp = 1;
+ PSCB(vcpu, vpsr_pp) = 1;
+ } else {
+ ipsr->pp = 1;
+ psr.pp = 1;
+ PSCB(vcpu, vpsr_pp) = 0;
}
- else {
- ipsr->pp = 1; psr.pp = 1;
- PSCB(vcpu,vpsr_pp) = 0;
+ if (newpsr.up) {
+ ipsr->up = 1;
+ psr.up = 1;
+ }
+ if (newpsr.sp) {
+ ipsr->sp = 1;
+ psr.sp = 1;
}
- if (newpsr.up) { ipsr->up = 1; psr.up = 1; }
- if (newpsr.sp) { ipsr->sp = 1; psr.sp = 1; }
if (newpsr.i) {
if (vcpu->vcpu_info->evtchn_upcall_mask)
enabling_interrupts = 1;
vcpu->vcpu_info->evtchn_upcall_mask = 0;
}
- if (newpsr.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
- if (newpsr.mfl) { ipsr->mfl = 1; psr.mfl = 1; }
- if (newpsr.mfh) { ipsr->mfh = 1; psr.mfh = 1; }
- if (newpsr.ac) { ipsr->ac = 1; psr.ac = 1; }
- if (newpsr.up) { ipsr->up = 1; psr.up = 1; }
- if (newpsr.dt && newpsr.rt) vcpu_set_metaphysical_mode(vcpu,FALSE);
- else vcpu_set_metaphysical_mode(vcpu,TRUE);
+ if (newpsr.ic)
+ PSCB(vcpu, interrupt_collection_enabled) = 1;
+ if (newpsr.mfl) {
+ ipsr->mfl = 1;
+ psr.mfl = 1;
+ }
+ if (newpsr.mfh) {
+ ipsr->mfh = 1;
+ psr.mfh = 1;
+ }
+ if (newpsr.ac) {
+ ipsr->ac = 1;
+ psr.ac = 1;
+ }
+ if (newpsr.up) {
+ ipsr->up = 1;
+ psr.up = 1;
+ }
+ if (newpsr.dt && newpsr.rt)
+ vcpu_set_metaphysical_mode(vcpu, FALSE);
+ else
+ vcpu_set_metaphysical_mode(vcpu, TRUE);
if (newpsr.be) {
printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
if (enabling_interrupts &&
- vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
- PSCB(vcpu,pending_interruption) = 1;
+ vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
+ PSCB(vcpu, pending_interruption) = 1;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_psr(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_psr(VCPU * vcpu, u64 * pval)
{
REGS *regs = vcpu_regs(vcpu);
struct ia64_psr newpsr;
newpsr = *(struct ia64_psr *)&regs->cr_ipsr;
- if (newpsr.cpl == 2) newpsr.cpl = 0;
- if (!vcpu->vcpu_info->evtchn_upcall_mask) newpsr.i = 1;
- else newpsr.i = 0;
- if (PSCB(vcpu,interrupt_collection_enabled)) newpsr.ic = 1;
- else newpsr.ic = 0;
- if (PSCB(vcpu,metaphysical_mode)) newpsr.dt = 0;
- else newpsr.dt = 1;
- if (PSCB(vcpu,vpsr_pp)) newpsr.pp = 1;
- else newpsr.pp = 0;
+ if (newpsr.cpl == 2)
+ newpsr.cpl = 0;
+ if (!vcpu->vcpu_info->evtchn_upcall_mask)
+ newpsr.i = 1;
+ else
+ newpsr.i = 0;
+ if (PSCB(vcpu, interrupt_collection_enabled))
+ newpsr.ic = 1;
+ else
+ newpsr.ic = 0;
+ if (PSCB(vcpu, metaphysical_mode))
+ newpsr.dt = 0;
+ else
+ newpsr.dt = 1;
+ if (PSCB(vcpu, vpsr_pp))
+ newpsr.pp = 1;
+ else
+ newpsr.pp = 0;
*pval = *(unsigned long *)&newpsr;
return IA64_NO_FAULT;
}
-BOOLEAN vcpu_get_psr_ic(VCPU *vcpu)
+BOOLEAN vcpu_get_psr_ic(VCPU * vcpu)
{
- return !!PSCB(vcpu,interrupt_collection_enabled);
+ return !!PSCB(vcpu, interrupt_collection_enabled);
}
-BOOLEAN vcpu_get_psr_i(VCPU *vcpu)
+BOOLEAN vcpu_get_psr_i(VCPU * vcpu)
{
return !vcpu->vcpu_info->evtchn_upcall_mask;
}
-UINT64 vcpu_get_ipsr_int_state(VCPU *vcpu,UINT64 prevpsr)
+u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr)
{
- UINT64 dcr = PSCBX(vcpu,dcr);
+ u64 dcr = PSCBX(vcpu, dcr);
PSR psr;
//printf("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr);
psr.i64 = prevpsr;
- psr.ia64_psr.be = 0; if (dcr & IA64_DCR_BE) psr.ia64_psr.be = 1;
- psr.ia64_psr.pp = 0; if (dcr & IA64_DCR_PP) psr.ia64_psr.pp = 1;
- psr.ia64_psr.ic = PSCB(vcpu,interrupt_collection_enabled);
+ psr.ia64_psr.be = 0;
+ if (dcr & IA64_DCR_BE)
+ psr.ia64_psr.be = 1;
+ psr.ia64_psr.pp = 0;
+ if (dcr & IA64_DCR_PP)
+ psr.ia64_psr.pp = 1;
+ psr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled);
psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask;
- psr.ia64_psr.bn = PSCB(vcpu,banknum);
- psr.ia64_psr.dt = 1; psr.ia64_psr.it = 1; psr.ia64_psr.rt = 1;
- if (psr.ia64_psr.cpl == 2) psr.ia64_psr.cpl = 0; // !!!! fool domain
+ psr.ia64_psr.bn = PSCB(vcpu, banknum);
+ psr.ia64_psr.dt = 1;
+ psr.ia64_psr.it = 1;
+ psr.ia64_psr.rt = 1;
+ if (psr.ia64_psr.cpl == 2)
+ psr.ia64_psr.cpl = 0; // !!!! fool domain
// psr.pk = 1;
//printf("returns 0x%016lx...\n",psr.i64);
return psr.i64;
@@ -426,223 +514,227 @@ UINT64 vcpu_get_ipsr_int_state(VCPU *vcpu,UINT64 prevpsr)
VCPU control register access routines
**************************************************************************/
-IA64FAULT vcpu_get_dcr(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_dcr(VCPU * vcpu, u64 * pval)
{
//verbose("vcpu_get_dcr: called @%p\n",PSCB(vcpu,iip));
// Reads of cr.dcr on Xen always have the sign bit set, so
// a domain can differentiate whether it is running on SP or not
- *pval = PSCBX(vcpu,dcr) | 0x8000000000000000L;
- return (IA64_NO_FAULT);
+ *pval = PSCBX(vcpu, dcr) | 0x8000000000000000L;
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_iva(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_iva(VCPU * vcpu, u64 * pval)
{
- if(VMX_DOMAIN(vcpu)){
- *pval = PSCB(vcpu,iva) & ~0x7fffL;
- }else{
- *pval = PSCBX(vcpu,iva) & ~0x7fffL;
- }
- return (IA64_NO_FAULT);
+ if (VMX_DOMAIN(vcpu))
+ *pval = PSCB(vcpu, iva) & ~0x7fffL;
+ else
+ *pval = PSCBX(vcpu, iva) & ~0x7fffL;
+
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_pta(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_pta(VCPU * vcpu, u64 * pval)
{
- *pval = PSCB(vcpu,pta);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, pta);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_ipsr(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_ipsr(VCPU * vcpu, u64 * pval)
{
//REGS *regs = vcpu_regs(vcpu);
//*pval = regs->cr_ipsr;
- *pval = PSCB(vcpu,ipsr);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, ipsr);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_isr(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_isr(VCPU * vcpu, u64 * pval)
{
- *pval = PSCB(vcpu,isr);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, isr);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_iip(VCPU * vcpu, u64 * pval)
{
//REGS *regs = vcpu_regs(vcpu);
//*pval = regs->cr_iip;
- *pval = PSCB(vcpu,iip);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, iip);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_ifa(VCPU * vcpu, u64 * pval)
{
PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_get_ifa);
- *pval = PSCB(vcpu,ifa);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, ifa);
+ return IA64_NO_FAULT;
}
-unsigned long vcpu_get_rr_ps(VCPU *vcpu,UINT64 vadr)
+unsigned long vcpu_get_rr_ps(VCPU * vcpu, u64 vadr)
{
ia64_rr rr;
- rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
- return(rr.ps);
+ rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
+ return rr.ps;
}
-unsigned long vcpu_get_rr_rid(VCPU *vcpu,UINT64 vadr)
+unsigned long vcpu_get_rr_rid(VCPU * vcpu, u64 vadr)
{
ia64_rr rr;
- rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
- return(rr.rid);
+ rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
+ return rr.rid;
}
-unsigned long vcpu_get_itir_on_fault(VCPU *vcpu, UINT64 ifa)
+unsigned long vcpu_get_itir_on_fault(VCPU * vcpu, u64 ifa)
{
ia64_rr rr;
rr.rrval = 0;
- rr.ps = vcpu_get_rr_ps(vcpu,ifa);
- rr.rid = vcpu_get_rr_rid(vcpu,ifa);
- return (rr.rrval);
+ rr.ps = vcpu_get_rr_ps(vcpu, ifa);
+ rr.rid = vcpu_get_rr_rid(vcpu, ifa);
+ return rr.rrval;
}
-
-IA64FAULT vcpu_get_itir(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_itir(VCPU * vcpu, u64 * pval)
{
- UINT64 val = PSCB(vcpu,itir);
+ u64 val = PSCB(vcpu, itir);
*pval = val;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_iipa(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_iipa(VCPU * vcpu, u64 * pval)
{
- UINT64 val = PSCB(vcpu,iipa);
+ u64 val = PSCB(vcpu, iipa);
// SP entry code does not save iipa yet nor does it get
// properly delivered in the pscb
// printf("*** vcpu_get_iipa: cr.iipa not fully implemented yet!!\n");
*pval = val;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_ifs(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_ifs(VCPU * vcpu, u64 * pval)
{
//PSCB(vcpu,ifs) = PSCB(vcpu)->regs.cr_ifs;
//*pval = PSCB(vcpu,regs).cr_ifs;
- *pval = PSCB(vcpu,ifs);
- PSCB(vcpu,incomplete_regframe) = 0;
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, ifs);
+ PSCB(vcpu, incomplete_regframe) = 0;
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_iim(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_iim(VCPU * vcpu, u64 * pval)
{
- UINT64 val = PSCB(vcpu,iim);
+ u64 val = PSCB(vcpu, iim);
*pval = val;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_iha(VCPU * vcpu, u64 * pval)
{
PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_thash);
- *pval = PSCB(vcpu,iha);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, iha);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_dcr(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_dcr(VCPU * vcpu, u64 val)
{
// Reads of cr.dcr on SP always have the sign bit set, so
// a domain can differentiate whether it is running on SP or not
// Thus, writes of DCR should ignore the sign bit
//verbose("vcpu_set_dcr: called\n");
- PSCBX(vcpu,dcr) = val & ~0x8000000000000000L;
- return (IA64_NO_FAULT);
+ PSCBX(vcpu, dcr) = val & ~0x8000000000000000L;
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_iva(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_iva(VCPU * vcpu, u64 val)
{
- if(VMX_DOMAIN(vcpu)){
- PSCB(vcpu,iva) = val & ~0x7fffL;
- }else{
- PSCBX(vcpu,iva) = val & ~0x7fffL;
- }
- return (IA64_NO_FAULT);
+ if (VMX_DOMAIN(vcpu))
+ PSCB(vcpu, iva) = val & ~0x7fffL;
+ else
+ PSCBX(vcpu, iva) = val & ~0x7fffL;
+
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_pta(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_pta(VCPU * vcpu, u64 val)
{
if (val & IA64_PTA_LFMT) {
printf("*** No support for VHPT long format yet!!\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
- if (val & (0x3f<<9)) /* reserved fields */ return IA64_RSVDREG_FAULT;
- if (val & 2) /* reserved fields */ return IA64_RSVDREG_FAULT;
- PSCB(vcpu,pta) = val;
+ if (val & (0x3f << 9)) /* reserved fields */
+ return IA64_RSVDREG_FAULT;
+ if (val & 2) /* reserved fields */
+ return IA64_RSVDREG_FAULT;
+ PSCB(vcpu, pta) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_ipsr(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_ipsr(VCPU * vcpu, u64 val)
{
- PSCB(vcpu,ipsr) = val;
+ PSCB(vcpu, ipsr) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_isr(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_isr(VCPU * vcpu, u64 val)
{
- PSCB(vcpu,isr) = val;
+ PSCB(vcpu, isr) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_iip(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_iip(VCPU * vcpu, u64 val)
{
- PSCB(vcpu,iip) = val;
+ PSCB(vcpu, iip) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_increment_iip(VCPU *vcpu)
+IA64FAULT vcpu_increment_iip(VCPU * vcpu)
{
REGS *regs = vcpu_regs(vcpu);
struct ia64_psr *ipsr = (struct ia64_psr *)&regs->cr_ipsr;
- if (ipsr->ri == 2) { ipsr->ri=0; regs->cr_iip += 16; }
- else ipsr->ri++;
- return (IA64_NO_FAULT);
+ if (ipsr->ri == 2) {
+ ipsr->ri = 0;
+ regs->cr_iip += 16;
+ } else
+ ipsr->ri++;
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_ifa(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_ifa(VCPU * vcpu, u64 val)
{
- PSCB(vcpu,ifa) = val;
+ PSCB(vcpu, ifa) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_itir(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_itir(VCPU * vcpu, u64 val)
{
- PSCB(vcpu,itir) = val;
+ PSCB(vcpu, itir) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_iipa(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_iipa(VCPU * vcpu, u64 val)
{
// SP entry code does not save iipa yet nor does it get
// properly delivered in the pscb
// printf("*** vcpu_set_iipa: cr.iipa not fully implemented yet!!\n");
- PSCB(vcpu,iipa) = val;
+ PSCB(vcpu, iipa) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_ifs(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_ifs(VCPU * vcpu, u64 val)
{
//REGS *regs = vcpu_regs(vcpu);
- PSCB(vcpu,ifs) = val;
+ PSCB(vcpu, ifs) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_iim(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_iim(VCPU * vcpu, u64 val)
{
- PSCB(vcpu,iim) = val;
+ PSCB(vcpu, iim) = val;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_iha(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_iha(VCPU * vcpu, u64 val)
{
- PSCB(vcpu,iha) = val;
+ PSCB(vcpu, iha) = val;
return IA64_NO_FAULT;
}
@@ -650,12 +742,12 @@ IA64FAULT vcpu_set_iha(VCPU *vcpu, UINT64 val)
VCPU interrupt control register access routines
**************************************************************************/
-void vcpu_pend_unspecified_interrupt(VCPU *vcpu)
+void vcpu_pend_unspecified_interrupt(VCPU * vcpu)
{
- PSCB(vcpu,pending_interruption) = 1;
+ PSCB(vcpu, pending_interruption) = 1;
}
-void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
+void vcpu_pend_interrupt(VCPU * vcpu, u64 vector)
{
if (vector & ~0xff) {
printf("vcpu_pend_interrupt: bad vector\n");
@@ -663,15 +755,16 @@ void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
}
if (vcpu->arch.event_callback_ip) {
- printf("Deprecated interface. Move to new event based solution\n");
+ printf("Deprecated interface. Move to new event based "
+ "solution\n");
return;
}
-
- if ( VMX_DOMAIN(vcpu) ) {
- set_bit(vector,VCPU(vcpu,irr));
+
+ if (VMX_DOMAIN(vcpu)) {
+ set_bit(vector, VCPU(vcpu, irr));
} else {
- set_bit(vector,PSCBX(vcpu,irr));
- PSCB(vcpu,pending_interruption) = 1;
+ set_bit(vector, PSCBX(vcpu, irr));
+ PSCB(vcpu, pending_interruption) = 1;
}
}
@@ -684,9 +777,9 @@ void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
* semantics of "mov rx=cr.ivr" ignore the setting of the psr.i bit,
* this routine also ignores pscb.interrupt_delivery_enabled
* and this must be checked independently; see vcpu_deliverable interrupts() */
-UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
+u64 vcpu_check_pending_interrupts(VCPU * vcpu)
{
- UINT64 *p, *r, bits, bitnum, mask, i, vector;
+ u64 *p, *r, bits, bitnum, mask, i, vector;
if (vcpu->arch.event_callback_ip)
return SPURIOUS_VECTOR;
@@ -695,38 +788,41 @@ UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
* event injection without handle. Later guest may throw out
* the event itself.
*/
-check_start:
- if (event_pending(vcpu) &&
- !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
- &PSCBX(vcpu, insvc[0])))
- vcpu_pend_interrupt(vcpu, vcpu->domain->shared_info->arch.evtchn_vector);
-
- p = &PSCBX(vcpu,irr[3]);
- r = &PSCBX(vcpu,insvc[3]);
- for (i = 3; ; p--, r--, i--) {
- bits = *p ;
- if (bits) break; // got a potential interrupt
+ check_start:
+ if (event_pending(vcpu) &&
+ !test_bit(vcpu->domain->shared_info->arch.evtchn_vector,
+ &PSCBX(vcpu, insvc[0])))
+ vcpu_pend_interrupt(vcpu,
+ vcpu->domain->shared_info->arch.
+ evtchn_vector);
+
+ p = &PSCBX(vcpu, irr[3]);
+ r = &PSCBX(vcpu, insvc[3]);
+ for (i = 3 ;; p--, r--, i--) {
+ bits = *p;
+ if (bits)
+ break; // got a potential interrupt
if (*r) {
// nothing in this word which is pending+inservice
// but there is one inservice which masks lower
return SPURIOUS_VECTOR;
}
if (i == 0) {
- // checked all bits... nothing pending+inservice
+ // checked all bits... nothing pending+inservice
return SPURIOUS_VECTOR;
}
}
// have a pending,deliverable interrupt... see if it is masked
bitnum = ia64_fls(bits);
//printf("XXXXXXX vcpu_check_pending_interrupts: got bitnum=%p...\n",bitnum);
- vector = bitnum+(i*64);
+ vector = bitnum + (i * 64);
mask = 1L << bitnum;
/* sanity check for guest timer interrupt */
- if (vector == (PSCB(vcpu,itv) & 0xff)) {
+ if (vector == (PSCB(vcpu, itv) & 0xff)) {
uint64_t now = ia64_get_itc();
- if (now < PSCBX(vcpu,domain_itm)) {
+ if (now < PSCBX(vcpu, domain_itm)) {
// printk("Ooops, pending guest timer before its due\n");
- PSCBX(vcpu,irr[i]) &= ~mask;
+ PSCBX(vcpu, irr[i]) &= ~mask;
goto check_start;
}
}
@@ -736,48 +832,47 @@ check_start:
//printf("but masked by equal inservice\n");
return SPURIOUS_VECTOR;
}
- if (PSCB(vcpu,tpr) & IA64_TPR_MMI) {
+ if (PSCB(vcpu, tpr) & IA64_TPR_MMI) {
// tpr.mmi is set
//printf("but masked by tpr.mmi\n");
return SPURIOUS_VECTOR;
}
- if (((PSCB(vcpu,tpr) & IA64_TPR_MIC) + 15) >= vector) {
+ if (((PSCB(vcpu, tpr) & IA64_TPR_MIC) + 15) >= vector) {
//tpr.mic masks class
//printf("but masked by tpr.mic\n");
return SPURIOUS_VECTOR;
}
-
//printf("returned to caller\n");
return vector;
}
-UINT64 vcpu_deliverable_interrupts(VCPU *vcpu)
+u64 vcpu_deliverable_interrupts(VCPU * vcpu)
{
return (vcpu_get_psr_i(vcpu) &&
vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR);
}
-UINT64 vcpu_deliverable_timer(VCPU *vcpu)
+u64 vcpu_deliverable_timer(VCPU * vcpu)
{
return (vcpu_get_psr_i(vcpu) &&
- vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu,itv));
+ vcpu_check_pending_interrupts(vcpu) == PSCB(vcpu, itv));
}
-IA64FAULT vcpu_get_lid(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval)
{
/* Use EID=0, ID=vcpu_id. */
*pval = vcpu->vcpu_id << 24;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval)
{
int i;
- UINT64 vector, mask;
+ u64 vector, mask;
#define HEARTBEAT_FREQ 16 // period in seconds
#ifdef HEARTBEAT_FREQ
-#define N_DOMS 16 // period in seconds
+#define N_DOMS 16 // period in seconds
#if 0
static long count[N_DOMS] = { 0 };
#endif
@@ -789,257 +884,269 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
static char firsttime[256];
if (firstivr) {
int i;
- for (i=0;i<256;i++) firsttime[i]=1;
- firstivr=0;
+ for (i = 0; i < 256; i++)
+ firsttime[i] = 1;
+ firstivr = 0;
}
#endif
vector = vcpu_check_pending_interrupts(vcpu);
if (vector == SPURIOUS_VECTOR) {
- PSCB(vcpu,pending_interruption) = 0;
+ PSCB(vcpu, pending_interruption) = 0;
*pval = vector;
return IA64_NO_FAULT;
}
#ifdef HEARTBEAT_FREQ
- if (domid >= N_DOMS) domid = N_DOMS-1;
+ if (domid >= N_DOMS)
+ domid = N_DOMS - 1;
#if 0
- if (vector == (PSCB(vcpu,itv) & 0xff)) {
- if (!(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) {
- printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
- domid, count[domid], nonclockcount[domid]);
- //count[domid] = 0;
- //dump_runq();
- }
+ if (vector == (PSCB(vcpu, itv) & 0xff)) {
+ if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) {
+ printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
+ domid, count[domid], nonclockcount[domid]);
+ //count[domid] = 0;
+ //dump_runq();
+ }
}
#endif
- else nonclockcount[domid]++;
+ else
+ nonclockcount[domid]++;
#endif
// now have an unmasked, pending, deliverable vector!
// getting ivr has "side effects"
#ifdef IRQ_DEBUG
if (firsttime[vector]) {
printf("*** First get_ivr on vector=%lu,itc=%lx\n",
- vector,ia64_get_itc());
- firsttime[vector]=0;
+ vector, ia64_get_itc());
+ firsttime[vector] = 0;
}
#endif
/* if delivering a timer interrupt, remember domain_itm, which
* needs to be done before clearing irr
*/
- if (vector == (PSCB(vcpu,itv) & 0xff)) {
- PSCBX(vcpu,domain_itm_last) = PSCBX(vcpu,domain_itm);
+ if (vector == (PSCB(vcpu, itv) & 0xff)) {
+ PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm);
}
i = vector >> 6;
mask = 1L << (vector & 0x3f);
//printf("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector);
- PSCBX(vcpu,insvc[i]) |= mask;
- PSCBX(vcpu,irr[i]) &= ~mask;
+ PSCBX(vcpu, insvc[i]) |= mask;
+ PSCBX(vcpu, irr[i]) &= ~mask;
//PSCB(vcpu,pending_interruption)--;
*pval = vector;
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_tpr(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval)
{
- *pval = PSCB(vcpu,tpr);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, tpr);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_eoi(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval)
{
- *pval = 0L; // reads of eoi always return 0
- return (IA64_NO_FAULT);
+ *pval = 0L; // reads of eoi always return 0
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_irr0(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval)
{
*pval = PSCBX(vcpu, irr[0]);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_irr1(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval)
{
*pval = PSCBX(vcpu, irr[1]);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_irr2(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval)
{
*pval = PSCBX(vcpu, irr[2]);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_irr3(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval)
{
*pval = PSCBX(vcpu, irr[3]);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_itv(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval)
{
- *pval = PSCB(vcpu,itv);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, itv);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_pmv(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval)
{
- *pval = PSCB(vcpu,pmv);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, pmv);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_cmcv(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval)
{
- *pval = PSCB(vcpu,cmcv);
- return (IA64_NO_FAULT);
+ *pval = PSCB(vcpu, cmcv);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_lrr0(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval)
{
// fix this when setting values other than m-bit is supported
printf("vcpu_get_lrr0: Unmasked interrupts unsupported\n");
*pval = (1L << 16);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_lrr1(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval)
{
// fix this when setting values other than m-bit is supported
printf("vcpu_get_lrr1: Unmasked interrupts unsupported\n");
*pval = (1L << 16);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_lid(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val)
{
printf("vcpu_set_lid: Setting cr.lid is unsupported\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
-IA64FAULT vcpu_set_tpr(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val)
{
- if (val & 0xff00) return IA64_RSVDREG_FAULT;
- PSCB(vcpu,tpr) = val;
+ if (val & 0xff00)
+ return IA64_RSVDREG_FAULT;
+ PSCB(vcpu, tpr) = val;
/* This can unmask interrupts. */
if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
- PSCB(vcpu,pending_interruption) = 1;
- return (IA64_NO_FAULT);
+ PSCB(vcpu, pending_interruption) = 1;
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_eoi(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val)
{
- UINT64 *p, bits, vec, bitnum;
+ u64 *p, bits, vec, bitnum;
int i;
- p = &PSCBX(vcpu,insvc[3]);
- for (i = 3; (i >= 0) && !(bits = *p); i--, p--);
+ p = &PSCBX(vcpu, insvc[3]);
+ for (i = 3; (i >= 0) && !(bits = *p); i--, p--)
+ ;
if (i < 0) {
printf("Trying to EOI interrupt when none are in-service.\n");
return IA64_NO_FAULT;
}
bitnum = ia64_fls(bits);
- vec = bitnum + (i*64);
+ vec = bitnum + (i * 64);
/* clear the correct bit */
bits &= ~(1L << bitnum);
*p = bits;
/* clearing an eoi bit may unmask another pending interrupt... */
- if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
+ if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled...
// worry about this later... Linux only calls eoi
// with interrupts disabled
printf("Trying to EOI interrupt with interrupts enabled\n");
}
if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR)
- PSCB(vcpu,pending_interruption) = 1;
+ PSCB(vcpu, pending_interruption) = 1;
//printf("YYYYY vcpu_set_eoi: Successful\n");
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_lrr0(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val)
{
if (!(val & (1L << 16))) {
printf("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
// no place to save this state but nothing to do anyway
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_lrr1(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val)
{
if (!(val & (1L << 16))) {
printf("vcpu_set_lrr0: Unmasked interrupts unsupported\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
// no place to save this state but nothing to do anyway
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_itv(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val)
{
/* Check reserved fields. */
if (val & 0xef00)
- return (IA64_ILLOP_FAULT);
- PSCB(vcpu,itv) = val;
+ return IA64_ILLOP_FAULT;
+ PSCB(vcpu, itv) = val;
if (val & 0x10000) {
/* Disable itm. */
- PSCBX(vcpu,domain_itm) = 0;
- }
- else vcpu_set_next_timer(vcpu);
- return (IA64_NO_FAULT);
+ PSCBX(vcpu, domain_itm) = 0;
+ } else
+ vcpu_set_next_timer(vcpu);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_pmv(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val)
{
- if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT;
- PSCB(vcpu,pmv) = val;
- return (IA64_NO_FAULT);
+ if (val & 0xef00) /* reserved fields */
+ return IA64_RSVDREG_FAULT;
+ PSCB(vcpu, pmv) = val;
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_cmcv(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val)
{
- if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT;
- PSCB(vcpu,cmcv) = val;
- return (IA64_NO_FAULT);
+ if (val & 0xef00) /* reserved fields */
+ return IA64_RSVDREG_FAULT;
+ PSCB(vcpu, cmcv) = val;
+ return IA64_NO_FAULT;
}
/**************************************************************************
VCPU temporary register access routines
**************************************************************************/
-UINT64 vcpu_get_tmp(VCPU *vcpu, UINT64 index)
+u64 vcpu_get_tmp(VCPU * vcpu, u64 index)
{
- if (index > 7) return 0;
- return PSCB(vcpu,tmp[index]);
+ if (index > 7)
+ return 0;
+ return PSCB(vcpu, tmp[index]);
}
-void vcpu_set_tmp(VCPU *vcpu, UINT64 index, UINT64 val)
+void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val)
{
- if (index <= 7) PSCB(vcpu,tmp[index]) = val;
+ if (index <= 7)
+ PSCB(vcpu, tmp[index]) = val;
}
/**************************************************************************
Interval timer routines
**************************************************************************/
-BOOLEAN vcpu_timer_disabled(VCPU *vcpu)
+BOOLEAN vcpu_timer_disabled(VCPU * vcpu)
{
- UINT64 itv = PSCB(vcpu,itv);
- return(!itv || !!(itv & 0x10000));
+ u64 itv = PSCB(vcpu, itv);
+ return (!itv || !!(itv & 0x10000));
}
-BOOLEAN vcpu_timer_inservice(VCPU *vcpu)
+BOOLEAN vcpu_timer_inservice(VCPU * vcpu)
{
- UINT64 itv = PSCB(vcpu,itv);
- return (test_bit(itv, PSCBX(vcpu,insvc)));
+ u64 itv = PSCB(vcpu, itv);
+ return test_bit(itv, PSCBX(vcpu, insvc));
}
-BOOLEAN vcpu_timer_expired(VCPU *vcpu)
+BOOLEAN vcpu_timer_expired(VCPU * vcpu)
{
- unsigned long domain_itm = PSCBX(vcpu,domain_itm);
+ unsigned long domain_itm = PSCBX(vcpu, domain_itm);
unsigned long now = ia64_get_itc();
- if (!domain_itm) return FALSE;
- if (now < domain_itm) return FALSE;
- if (vcpu_timer_disabled(vcpu)) return FALSE;
+ if (!domain_itm)
+ return FALSE;
+ if (now < domain_itm)
+ return FALSE;
+ if (vcpu_timer_disabled(vcpu))
+ return FALSE;
return TRUE;
}
@@ -1047,25 +1154,26 @@ void vcpu_safe_set_itm(unsigned long val)
{
unsigned long epsilon = 100;
unsigned long flags;
- UINT64 now = ia64_get_itc();
+ u64 now = ia64_get_itc();
local_irq_save(flags);
while (1) {
//printf("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now);
ia64_set_itm(val);
- if (val > (now = ia64_get_itc())) break;
+ if (val > (now = ia64_get_itc()))
+ break;
val = now + epsilon;
epsilon <<= 1;
}
local_irq_restore(flags);
}
-void vcpu_set_next_timer(VCPU *vcpu)
+void vcpu_set_next_timer(VCPU * vcpu)
{
- UINT64 d = PSCBX(vcpu,domain_itm);
- //UINT64 s = PSCBX(vcpu,xen_itm);
- UINT64 s = local_cpu_data->itm_next;
- UINT64 now = ia64_get_itc();
+ u64 d = PSCBX(vcpu, domain_itm);
+ //u64 s = PSCBX(vcpu,xen_itm);
+ u64 s = local_cpu_data->itm_next;
+ u64 now = ia64_get_itc();
/* gloss over the wraparound problem for now... we know it exists
* but it doesn't matter right now */
@@ -1079,25 +1187,24 @@ void vcpu_set_next_timer(VCPU *vcpu)
if (d && (d > now) && (d < s)) {
vcpu_safe_set_itm(d);
//using_domain_as_itm++;
- }
- else {
+ } else {
vcpu_safe_set_itm(s);
//using_xen_as_itm++;
}
}
-IA64FAULT vcpu_set_itm(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val)
{
//UINT now = ia64_get_itc();
//if (val < now) val = now + 1000;
//printf("*** vcpu_set_itm: called with %lx\n",val);
- PSCBX(vcpu,domain_itm) = val;
+ PSCBX(vcpu, domain_itm) = val;
vcpu_set_next_timer(vcpu);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_itc(VCPU *vcpu, UINT64 val)
+IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val)
{
#define DISALLOW_SETTING_ITC_FOR_NOW
#ifdef DISALLOW_SETTING_ITC_FOR_NOW
@@ -1108,58 +1215,59 @@ IA64FAULT vcpu_set_itc(VCPU *vcpu, UINT64 val)
did_print = 1;
}
#else
- UINT64 oldnow = ia64_get_itc();
- UINT64 olditm = PSCBX(vcpu,domain_itm);
+ u64 oldnow = ia64_get_itc();
+ u64 olditm = PSCBX(vcpu, domain_itm);
unsigned long d = olditm - oldnow;
unsigned long x = local_cpu_data->itm_next - oldnow;
- UINT64 newnow = val, min_delta;
+ u64 newnow = val, min_delta;
local_irq_disable();
if (olditm) {
-printf("**** vcpu_set_itc(%lx): vitm changed to %lx\n",val,newnow+d);
- PSCBX(vcpu,domain_itm) = newnow + d;
+ printf("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val,
+ newnow + d);
+ PSCBX(vcpu, domain_itm) = newnow + d;
}
local_cpu_data->itm_next = newnow + x;
- d = PSCBX(vcpu,domain_itm);
+ d = PSCBX(vcpu, domain_itm);
x = local_cpu_data->itm_next;
ia64_set_itc(newnow);
if (d && (d > newnow) && (d < x)) {
vcpu_safe_set_itm(d);
//using_domain_as_itm++;
- }
- else {
+ } else {
vcpu_safe_set_itm(x);
//using_xen_as_itm++;
}
local_irq_enable();
#endif
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_itm(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval)
{
//FIXME: Implement this
printf("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n");
- return (IA64_NO_FAULT);
- //return (IA64_ILLOP_FAULT);
+ return IA64_NO_FAULT;
+ //return IA64_ILLOP_FAULT;
}
-IA64FAULT vcpu_get_itc(VCPU *vcpu, UINT64 *pval)
+IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval)
{
//TODO: Implement this
printf("vcpu_get_itc: Getting ar.itc is unsupported\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
-void vcpu_pend_timer(VCPU *vcpu)
+void vcpu_pend_timer(VCPU * vcpu)
{
- UINT64 itv = PSCB(vcpu,itv) & 0xff;
+ u64 itv = PSCB(vcpu, itv) & 0xff;
- if (vcpu_timer_disabled(vcpu)) return;
+ if (vcpu_timer_disabled(vcpu))
+ return;
//if (vcpu_timer_inservice(vcpu)) return;
- if (PSCBX(vcpu,domain_itm_last) == PSCBX(vcpu,domain_itm)) {
+ if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) {
// already delivered an interrupt for this so
// don't deliver another
return;
@@ -1177,13 +1285,15 @@ void vcpu_pend_timer(VCPU *vcpu)
}
// returns true if ready to deliver a timer interrupt too early
-UINT64 vcpu_timer_pending_early(VCPU *vcpu)
+u64 vcpu_timer_pending_early(VCPU * vcpu)
{
- UINT64 now = ia64_get_itc();
- UINT64 itm = PSCBX(vcpu,domain_itm);
+ u64 now = ia64_get_itc();
+ u64 itm = PSCBX(vcpu, domain_itm);
- if (vcpu_timer_disabled(vcpu)) return 0;
- if (!itm) return 0;
+ if (vcpu_timer_disabled(vcpu))
+ return 0;
+ if (!itm)
+ return 0;
return (vcpu_deliverable_timer(vcpu) && (now < itm));
}
@@ -1191,120 +1301,129 @@ UINT64 vcpu_timer_pending_early(VCPU *vcpu)
Privileged operation emulation routines
**************************************************************************/
-static void
-vcpu_force_tlb_miss(VCPU* vcpu, UINT64 ifa)
+static void vcpu_force_tlb_miss(VCPU * vcpu, u64 ifa)
{
PSCB(vcpu, ifa) = ifa;
PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
vcpu_thash(current, ifa, &PSCB(current, iha));
}
-IA64FAULT vcpu_force_inst_miss(VCPU *vcpu, UINT64 ifa)
+IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa)
{
vcpu_force_tlb_miss(vcpu, ifa);
- return (vcpu_get_rr_ve(vcpu, ifa)? IA64_INST_TLB_VECTOR: IA64_ALT_INST_TLB_VECTOR);
+ return vcpu_get_rr_ve(vcpu, ifa) ? IA64_INST_TLB_VECTOR :
+ IA64_ALT_INST_TLB_VECTOR;
}
-IA64FAULT vcpu_force_data_miss(VCPU *vcpu, UINT64 ifa)
+IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa)
{
vcpu_force_tlb_miss(vcpu, ifa);
- return (vcpu_get_rr_ve(vcpu, ifa)? IA64_DATA_TLB_VECTOR: IA64_ALT_DATA_TLB_VECTOR);
+ return vcpu_get_rr_ve(vcpu, ifa) ? IA64_DATA_TLB_VECTOR :
+ IA64_ALT_DATA_TLB_VECTOR;
}
-IA64FAULT vcpu_rfi(VCPU *vcpu)
+IA64FAULT vcpu_rfi(VCPU * vcpu)
{
// TODO: Only allowed for current vcpu
PSR psr;
- UINT64 int_enable, regspsr = 0;
- UINT64 ifs;
+ u64 int_enable, regspsr = 0;
+ u64 ifs;
REGS *regs = vcpu_regs(vcpu);
extern void dorfirfi(void);
- psr.i64 = PSCB(vcpu,ipsr);
- if (psr.ia64_psr.cpl < 3) psr.ia64_psr.cpl = 2;
+ psr.i64 = PSCB(vcpu, ipsr);
+ if (psr.ia64_psr.cpl < 3)
+ psr.ia64_psr.cpl = 2;
int_enable = psr.ia64_psr.i;
- if (psr.ia64_psr.ic) PSCB(vcpu,interrupt_collection_enabled) = 1;
- if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it) vcpu_set_metaphysical_mode(vcpu,FALSE);
- else vcpu_set_metaphysical_mode(vcpu,TRUE);
- psr.ia64_psr.ic = 1; psr.ia64_psr.i = 1;
- psr.ia64_psr.dt = 1; psr.ia64_psr.rt = 1; psr.ia64_psr.it = 1;
+ if (psr.ia64_psr.ic)
+ PSCB(vcpu, interrupt_collection_enabled) = 1;
+ if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it)
+ vcpu_set_metaphysical_mode(vcpu, FALSE);
+ else
+ vcpu_set_metaphysical_mode(vcpu, TRUE);
+ psr.ia64_psr.ic = 1;
+ psr.ia64_psr.i = 1;
+ psr.ia64_psr.dt = 1;
+ psr.ia64_psr.rt = 1;
+ psr.ia64_psr.it = 1;
psr.ia64_psr.bn = 1;
//psr.pk = 1; // checking pkeys shouldn't be a problem but seems broken
if (psr.ia64_psr.be) {
printf("*** DOMAIN TRYING TO TURN ON BIG-ENDIAN!!!\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
- PSCB(vcpu,incomplete_regframe) = 0; // is this necessary?
- ifs = PSCB(vcpu,ifs);
+ PSCB(vcpu, incomplete_regframe) = 0; // is this necessary?
+ ifs = PSCB(vcpu, ifs);
//if ((ifs & regs->cr_ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
//if ((ifs & 0x8000000000000000L) && ifs != regs->cr_ifs) {
if (ifs & regs->cr_ifs & 0x8000000000000000L) {
// TODO: validate PSCB(vcpu,iip)
// TODO: PSCB(vcpu,ipsr) = psr;
- PSCB(vcpu,ipsr) = psr.i64;
+ PSCB(vcpu, ipsr) = psr.i64;
// now set up the trampoline
regs->cr_iip = *(unsigned long *)dorfirfi; // function pointer!!
- __asm__ __volatile ("mov %0=psr;;":"=r"(regspsr)::"memory");
- regs->cr_ipsr = regspsr & ~(IA64_PSR_I | IA64_PSR_IC | IA64_PSR_BN);
- }
- else {
+ __asm__ __volatile("mov %0=psr;;":"=r"(regspsr)::"memory");
+ regs->cr_ipsr =
+ regspsr & ~(IA64_PSR_I | IA64_PSR_IC | IA64_PSR_BN);
+ } else {
regs->cr_ipsr = psr.i64;
- regs->cr_iip = PSCB(vcpu,iip);
+ regs->cr_iip = PSCB(vcpu, iip);
}
- PSCB(vcpu,interrupt_collection_enabled) = 1;
+ PSCB(vcpu, interrupt_collection_enabled) = 1;
vcpu_bsw1(vcpu);
vcpu->vcpu_info->evtchn_upcall_mask = !int_enable;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_cover(VCPU *vcpu)
+IA64FAULT vcpu_cover(VCPU * vcpu)
{
// TODO: Only allowed for current vcpu
REGS *regs = vcpu_regs(vcpu);
- if (!PSCB(vcpu,interrupt_collection_enabled)) {
- if (!PSCB(vcpu,incomplete_regframe))
- PSCB(vcpu,ifs) = regs->cr_ifs;
- else PSCB(vcpu,incomplete_regframe) = 0;
+ if (!PSCB(vcpu, interrupt_collection_enabled)) {
+ if (!PSCB(vcpu, incomplete_regframe))
+ PSCB(vcpu, ifs) = regs->cr_ifs;
+ else
+ PSCB(vcpu, incomplete_regframe) = 0;
}
regs->cr_ifs = 0;
- return (IA64_NO_FAULT);
-}
-
-IA64FAULT vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
-{
- UINT64 pta = PSCB(vcpu,pta);
- UINT64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
- UINT64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT)-1);
- UINT64 Mask = (1L << pta_sz) - 1;
- UINT64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
- UINT64 compMask_60_15 = ~Mask_60_15;
- UINT64 rr_ps = vcpu_get_rr_ps(vcpu,vadr);
- UINT64 VHPT_offset = (vadr >> rr_ps) << 3;
- UINT64 VHPT_addr1 = vadr & 0xe000000000000000L;
- UINT64 VHPT_addr2a =
- ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
- UINT64 VHPT_addr2b =
- ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
- UINT64 VHPT_addr3 = VHPT_offset & 0x7fff;
- UINT64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
- VHPT_addr3;
+ return IA64_NO_FAULT;
+}
+
+IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval)
+{
+ u64 pta = PSCB(vcpu, pta);
+ u64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT;
+ u64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT) - 1);
+ u64 Mask = (1L << pta_sz) - 1;
+ u64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff;
+ u64 compMask_60_15 = ~Mask_60_15;
+ u64 rr_ps = vcpu_get_rr_ps(vcpu, vadr);
+ u64 VHPT_offset = (vadr >> rr_ps) << 3;
+ u64 VHPT_addr1 = vadr & 0xe000000000000000L;
+ u64 VHPT_addr2a =
+ ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15;
+ u64 VHPT_addr2b =
+ ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15;
+ u64 VHPT_addr3 = VHPT_offset & 0x7fff;
+ u64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
+ VHPT_addr3;
//verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
*pval = VHPT_addr;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_ttag(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
+IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr)
{
printf("vcpu_ttag: ttag instruction unsupported\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
}
-int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
+int warn_region0_address = 0; // FIXME later: tie to a boot parameter?
/* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */
-static inline int range_overlap (u64 b1, u64 e1, u64 b2, u64 e2)
+static inline int range_overlap(u64 b1, u64 e1, u64 b2, u64 e2)
{
return (b1 <= e2) && (e1 >= b2);
}
@@ -1312,45 +1431,53 @@ static inline int range_overlap (u64 b1, u64 e1, u64 b2, u64 e2)
/* Crash domain if [base, base + page_size] and Xen virtual space overlaps.
Note: LSBs of base inside page_size are ignored. */
static inline void
-check_xen_space_overlap (const char *func, u64 base, u64 page_size)
+check_xen_space_overlap(const char *func, u64 base, u64 page_size)
{
+ /* Overlaps can occur only in region 7.
+ (This is an optimization to bypass all the checks). */
+ if (REGION_NUMBER(base) != 7)
+ return;
+
/* Mask LSBs of base. */
base &= ~(page_size - 1);
/* FIXME: ideally an MCA should be generated... */
- if (range_overlap (HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
- base, base + page_size))
- panic_domain (NULL, "%s on Xen virtual space (%lx)\n",
- func, base);
+ if (range_overlap(HYPERVISOR_VIRT_START, HYPERVISOR_VIRT_END,
+ base, base + page_size)
+ || range_overlap(current->domain->arch.shared_info_va,
+ current->domain->arch.shared_info_va
+ + XSI_SIZE + XMAPPEDREGS_SIZE,
+ base, base + page_size))
+ panic_domain(NULL, "%s on Xen virtual space (%lx)\n",
+ func, base);
}
// FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
-static inline int vcpu_match_tr_entry_no_p(TR_ENTRY *trp, UINT64 ifa, UINT64 rid)
+static inline int vcpu_match_tr_entry_no_p(TR_ENTRY * trp, u64 ifa,
+ u64 rid)
{
- return trp->rid == rid
- && ifa >= trp->vadr
- && ifa <= (trp->vadr + (1L << trp->ps) - 1);
+ return trp->rid == rid
+ && ifa >= trp->vadr && ifa <= (trp->vadr + (1L << trp->ps) - 1);
}
-static inline int vcpu_match_tr_entry(TR_ENTRY *trp, UINT64 ifa, UINT64 rid)
+static inline int vcpu_match_tr_entry(TR_ENTRY * trp, u64 ifa, u64 rid)
{
return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
}
static inline int
-vcpu_match_tr_entry_range(TR_ENTRY *trp, UINT64 rid, u64 b, u64 e)
+vcpu_match_tr_entry_range(TR_ENTRY * trp, u64 rid, u64 b, u64 e)
{
return trp->rid == rid
- && trp->pte.p
- && range_overlap (b, e,
- trp->vadr, trp->vadr + (1L << trp->ps) - 1);
+ && trp->pte.p
+ && range_overlap(b, e, trp->vadr, trp->vadr + (1L << trp->ps) - 1);
}
-static TR_ENTRY*
-vcpu_tr_lookup(VCPU* vcpu, unsigned long va, UINT64 rid, BOOLEAN is_data)
+static TR_ENTRY *vcpu_tr_lookup(VCPU * vcpu, unsigned long va, u64 rid,
+ BOOLEAN is_data)
{
- unsigned char* regions;
+ unsigned char *regions;
TR_ENTRY *trp;
int tr_max;
int i;
@@ -1359,12 +1486,12 @@ vcpu_tr_lookup(VCPU* vcpu, unsigned long va, UINT64 rid, BOOLEAN is_data)
// data
regions = &vcpu->arch.dtr_regions;
trp = vcpu->arch.dtrs;
- tr_max = sizeof(vcpu->arch.dtrs)/sizeof(vcpu->arch.dtrs[0]);
+ tr_max = sizeof(vcpu->arch.dtrs) / sizeof(vcpu->arch.dtrs[0]);
} else {
// instruction
regions = &vcpu->arch.itr_regions;
trp = vcpu->arch.itrs;
- tr_max = sizeof(vcpu->arch.itrs)/sizeof(vcpu->arch.itrs[0]);
+ tr_max = sizeof(vcpu->arch.itrs) / sizeof(vcpu->arch.itrs[0]);
}
if (!vcpu_quick_region_check(*regions, va)) {
@@ -1382,13 +1509,14 @@ vcpu_tr_lookup(VCPU* vcpu, unsigned long va, UINT64 rid, BOOLEAN is_data)
// 0: failure
// 1: success
int
-vcpu_get_domain_bundle(VCPU* vcpu, REGS* regs, UINT64 gip, IA64_BUNDLE* bundle)
+vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
+ IA64_BUNDLE * bundle)
{
- UINT64 gpip;// guest pseudo phyiscal ip
+ u64 gpip; // guest pseudo phyiscal ip
unsigned long vaddr;
- struct page_info* page;
+ struct page_info *page;
-again:
+ again:
#if 0
// Currently xen doesn't track psr.it bits.
// it assumes always psr.it = 1.
@@ -1401,7 +1529,7 @@ again:
unsigned long rr = PSCB(vcpu, rrs)[region];
unsigned long rid = rr & RR_RID_MASK;
BOOLEAN swap_rr0;
- TR_ENTRY* trp;
+ TR_ENTRY *trp;
// vcpu->arch.{i, d}tlb are volatile,
// copy its value to the variable, tr, before use.
@@ -1416,7 +1544,8 @@ again:
// Last itc.i value is cached to PSCBX(vcpu, itlb).
tr = PSCBX(vcpu, itlb);
if (vcpu_match_tr_entry(&tr, gip, rid)) {
- //DPRINTK("%s gip 0x%lx gpip 0x%lx\n", __func__, gip, gpip);
+ //DPRINTK("%s gip 0x%lx gpip 0x%lx\n", __func__,
+ // gip, gpip);
goto found;
}
trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
@@ -1446,43 +1575,43 @@ again:
return 0;
}
return 1;
-
+
found:
gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
(gip & ((1 << tr.ps) - 1));
}
-
+
vaddr = (unsigned long)domain_mpa_to_imva(vcpu->domain, gpip);
page = virt_to_page(vaddr);
if (get_page(page, vcpu->domain) == 0) {
if (page_get_owner(page) != vcpu->domain) {
// This page might be a page granted by another
// domain.
- panic_domain(regs,
- "domain tries to execute foreign domain "
- "page which might be mapped by grant "
- "table.\n");
+ panic_domain(regs, "domain tries to execute foreign "
+ "domain page which might be mapped by "
+ "grant table.\n");
}
goto again;
}
- *bundle = *((IA64_BUNDLE*)vaddr);
+ *bundle = *((IA64_BUNDLE *) vaddr);
put_page(page);
return 1;
}
-IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pteval, UINT64 *itir, UINT64 *iha)
+IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
+ u64 * pteval, u64 * itir, u64 * iha)
{
unsigned long region = address >> 61;
unsigned long pta, rid, rr;
union pte_flags pte;
TR_ENTRY *trp;
- if (PSCB(vcpu,metaphysical_mode) && !(!is_data && region)) {
+ if (PSCB(vcpu, metaphysical_mode) && !(!is_data && region)) {
// dom0 may generate an uncacheable physical address (msb=1)
if (region && ((region != 4) || (vcpu->domain != dom0))) {
// FIXME: This seems to happen even though it shouldn't. Need to track
// this down, but since it has been apparently harmless, just flag it for now
-// panic_domain(vcpu_regs(vcpu),
+// panic_domain(vcpu_regs(vcpu),
/*
* Guest may execute itc.d and rfi with psr.dt=0
@@ -1490,29 +1619,29 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pt
* At this time PSCB(vcpu,metaphysical_mode)=1,
* region=5,VMM need to handle this tlb miss as if
* PSCB(vcpu,metaphysical_mode)=0
- */
- printk("vcpu_translate: bad physical address: 0x%lx at %lx\n",
- address, vcpu_regs (vcpu)->cr_iip);
+ */
+ printk("vcpu_translate: bad physical address: 0x%lx "
+ "at %lx\n", address, vcpu_regs(vcpu)->cr_iip);
} else {
- *pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS |
- _PAGE_PL_2 | _PAGE_AR_RWX;
+ *pteval = (address & _PAGE_PPN_MASK) |
+ __DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX;
*itir = PAGE_SHIFT << 2;
perfc_incrc(phys_translate);
return IA64_NO_FAULT;
}
- }
- else if (!region && warn_region0_address) {
+ } else if (!region && warn_region0_address) {
REGS *regs = vcpu_regs(vcpu);
- unsigned long viip = PSCB(vcpu,iip);
- unsigned long vipsr = PSCB(vcpu,ipsr);
+ unsigned long viip = PSCB(vcpu, iip);
+ unsigned long vipsr = PSCB(vcpu, ipsr);
unsigned long iip = regs->cr_iip;
unsigned long ipsr = regs->cr_ipsr;
- printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
- address, viip, vipsr, iip, ipsr);
+ printk("vcpu_translate: bad address 0x%lx, viip=0x%lx, "
+ "vipsr=0x%lx, iip=0x%lx, ipsr=0x%lx continuing\n",
+ address, viip, vipsr, iip, ipsr);
}
- rr = PSCB(vcpu,rrs)[region];
+ rr = PSCB(vcpu, rrs)[region];
rid = rr & RR_RID_MASK;
if (is_data) {
trp = vcpu_tr_lookup(vcpu, address, rid, 1);
@@ -1524,7 +1653,7 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pt
}
}
// FIXME?: check itr's for data accesses too, else bad things happen?
- /* else */ {
+ /* else */ {
trp = vcpu_tr_lookup(vcpu, address, rid, 0);
if (trp != NULL) {
*pteval = trp->pte.val;
@@ -1538,8 +1667,8 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pt
// FIXME?: check dtlb for inst accesses too, else bad things happen?
trp = &vcpu->arch.dtlb;
pte = trp->pte;
- if (/* is_data && */ pte.p
- && vcpu_match_tr_entry_no_p(trp,address,rid)) {
+ if ( /* is_data && */ pte.p
+ && vcpu_match_tr_entry_no_p(trp, address, rid)) {
*pteval = pte.val;
*itir = trp->itir;
perfc_incrc(dtlb_translate);
@@ -1547,10 +1676,10 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pt
}
/* check guest VHPT */
- pta = PSCB(vcpu,pta);
+ pta = PSCB(vcpu, pta);
if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
- panic_domain(vcpu_regs(vcpu),"can't do long format VHPT\n");
- //return (is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR);
+ panic_domain(vcpu_regs(vcpu), "can't do long format VHPT\n");
+ //return is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR;
}
*itir = rr & (RR_RID_MASK | RR_PS_MASK);
@@ -1558,24 +1687,25 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pt
// xenlinux depends on it so should document it as part of PV interface
vcpu_thash(vcpu, address, iha);
if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE))
- return (is_data ? IA64_ALT_DATA_TLB_VECTOR : IA64_ALT_INST_TLB_VECTOR);
+ return is_data ? IA64_ALT_DATA_TLB_VECTOR :
+ IA64_ALT_INST_TLB_VECTOR;
/* avoid recursively walking (short format) VHPT */
if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
- return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
+ return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
- if (!__access_ok (*iha)
+ if (!__access_ok(*iha)
|| __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
// virtual VHPT walker "missed" in TLB
return IA64_VHPT_FAULT;
/*
- * Optimisation: this VHPT walker aborts on not-present pages
- * instead of inserting a not-present translation, this allows
- * vectoring directly to the miss handler.
- */
+ * Optimisation: this VHPT walker aborts on not-present pages
+ * instead of inserting a not-present translation, this allows
+ * vectoring directly to the miss handler.
+ */
if (!pte.p)
- return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
+ return is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR;
/* found mapping in guest VHPT! */
*itir = rr & RR_PS_MASK;
@@ -1584,25 +1714,24 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pt
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
+IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr)
{
- UINT64 pteval, itir, mask, iha;
+ u64 pteval, itir, mask, iha;
IA64FAULT fault;
fault = vcpu_translate(vcpu, vadr, TRUE, &pteval, &itir, &iha);
- if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB)
- {
+ if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) {
mask = itir_mask(itir);
*padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
- return vcpu_force_data_miss(vcpu,vadr);
+ return vcpu_force_data_miss(vcpu, vadr);
}
-IA64FAULT vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key)
+IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key)
{
printf("vcpu_tak: tak instruction unsupported\n");
- return (IA64_ILLOP_FAULT);
+ return IA64_ILLOP_FAULT;
// HACK ALERT: tak does a thash for now
//return vcpu_thash(vcpu,vadr,key);
}
@@ -1611,84 +1740,84 @@ IA64FAULT vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key)
VCPU debug breakpoint register access routines
**************************************************************************/
-IA64FAULT vcpu_set_dbr(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
{
// TODO: unimplemented DBRs return a reserved register fault
// TODO: Should set Logical CPU state, not just physical
- ia64_set_dbr(reg,val);
- return (IA64_NO_FAULT);
+ ia64_set_dbr(reg, val);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_ibr(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
{
// TODO: unimplemented IBRs return a reserved register fault
// TODO: Should set Logical CPU state, not just physical
- ia64_set_ibr(reg,val);
- return (IA64_NO_FAULT);
+ ia64_set_ibr(reg, val);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_dbr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
{
// TODO: unimplemented DBRs return a reserved register fault
- UINT64 val = ia64_get_dbr(reg);
+ u64 val = ia64_get_dbr(reg);
*pval = val;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_ibr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
{
// TODO: unimplemented IBRs return a reserved register fault
- UINT64 val = ia64_get_ibr(reg);
+ u64 val = ia64_get_ibr(reg);
*pval = val;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
/**************************************************************************
VCPU performance monitor register access routines
**************************************************************************/
-IA64FAULT vcpu_set_pmc(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val)
{
// TODO: Should set Logical CPU state, not just physical
// NOTE: Writes to unimplemented PMC registers are discarded
#ifdef DEBUG_PFMON
-printf("vcpu_set_pmc(%x,%lx)\n",reg,val);
+ printf("vcpu_set_pmc(%x,%lx)\n", reg, val);
#endif
- ia64_set_pmc(reg,val);
- return (IA64_NO_FAULT);
+ ia64_set_pmc(reg, val);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_pmd(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val)
{
// TODO: Should set Logical CPU state, not just physical
// NOTE: Writes to unimplemented PMD registers are discarded
#ifdef DEBUG_PFMON
-printf("vcpu_set_pmd(%x,%lx)\n",reg,val);
+ printf("vcpu_set_pmd(%x,%lx)\n", reg, val);
#endif
- ia64_set_pmd(reg,val);
- return (IA64_NO_FAULT);
+ ia64_set_pmd(reg, val);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_pmc(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval)
{
// NOTE: Reads from unimplemented PMC registers return zero
- UINT64 val = (UINT64)ia64_get_pmc(reg);
+ u64 val = (u64) ia64_get_pmc(reg);
#ifdef DEBUG_PFMON
-printf("%lx=vcpu_get_pmc(%x)\n",val,reg);
+ printf("%lx=vcpu_get_pmc(%x)\n", val, reg);
#endif
*pval = val;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_pmd(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval)
{
// NOTE: Reads from unimplemented PMD registers return zero
- UINT64 val = (UINT64)ia64_get_pmd(reg);
+ u64 val = (u64) ia64_get_pmd(reg);
#ifdef DEBUG_PFMON
-printf("%lx=vcpu_get_pmd(%x)\n",val,reg);
+ printf("%lx=vcpu_get_pmd(%x)\n", val, reg);
#endif
*pval = val;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
/**************************************************************************
@@ -1707,167 +1836,183 @@ do{ \
"r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
}while(0)
-IA64FAULT vcpu_bsw0(VCPU *vcpu)
+IA64FAULT vcpu_bsw0(VCPU * vcpu)
{
// TODO: Only allowed for current vcpu
REGS *regs = vcpu_regs(vcpu);
unsigned long *r = &regs->r16;
- unsigned long *b0 = &PSCB(vcpu,bank0_regs[0]);
- unsigned long *b1 = &PSCB(vcpu,bank1_regs[0]);
+ unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
+ unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
unsigned long *runat = &regs->eml_unat;
- unsigned long *b0unat = &PSCB(vcpu,vbnat);
- unsigned long *b1unat = &PSCB(vcpu,vnat);
+ unsigned long *b0unat = &PSCB(vcpu, vbnat);
+ unsigned long *b1unat = &PSCB(vcpu, vnat);
unsigned long i;
- if(VMX_DOMAIN(vcpu)){
- if(VCPU(vcpu,vpsr)&IA64_PSR_BN){
- for (i = 0; i < 16; i++) { *b1++ = *r; *r++ = *b0++; }
- vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
- VCPU(vcpu,vpsr) &= ~IA64_PSR_BN;
- }
- }else{
- if (PSCB(vcpu,banknum)) {
- for (i = 0; i < 16; i++) { *b1++ = *r; *r++ = *b0++; }
- vcpu_bsw0_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
- PSCB(vcpu,banknum) = 0;
- }
- }
- return (IA64_NO_FAULT);
-}
-
-#define vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT) \
-do{ \
- __asm__ __volatile__ ( \
- ";;extr.u %0 = %3,%6,16;;\n" \
- "dep %1 = %0, %1, 16, 16;;\n" \
- "st8 [%4] = %1\n" \
- "extr.u %0 = %2, 0, 16;;\n" \
- "dep %3 = %0, %3, %6, 16;;\n" \
- "st8 [%5] = %3\n" \
- ::"r"(i),"r"(*b0unat),"r"(*b1unat),"r"(*runat),"r"(b0unat), \
- "r"(runat),"i"(IA64_PT_REGS_R16_SLOT):"memory"); \
-}while(0)
+ if (VMX_DOMAIN(vcpu)) {
+ if (VCPU(vcpu, vpsr) & IA64_PSR_BN) {
+ for (i = 0; i < 16; i++) {
+ *b1++ = *r;
+ *r++ = *b0++;
+ }
+ vcpu_bsw0_unat(i, b0unat, b1unat, runat,
+ IA64_PT_REGS_R16_SLOT);
+ VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
+ }
+ } else {
+ if (PSCB(vcpu, banknum)) {
+ for (i = 0; i < 16; i++) {
+ *b1++ = *r;
+ *r++ = *b0++;
+ }
+ vcpu_bsw0_unat(i, b0unat, b1unat, runat,
+ IA64_PT_REGS_R16_SLOT);
+ PSCB(vcpu, banknum) = 0;
+ }
+ }
+ return IA64_NO_FAULT;
+}
+
+#define vcpu_bsw1_unat(i, b0unat, b1unat, runat, IA64_PT_REGS_R16_SLOT) \
+do { \
+ __asm__ __volatile__ (";;extr.u %0 = %3,%6,16;;\n" \
+ "dep %1 = %0, %1, 16, 16;;\n" \
+ "st8 [%4] = %1\n" \
+ "extr.u %0 = %2, 0, 16;;\n" \
+ "dep %3 = %0, %3, %6, 16;;\n" \
+ "st8 [%5] = %3\n" \
+ ::"r"(i), "r"(*b0unat), "r"(*b1unat), \
+ "r"(*runat), "r"(b0unat), "r"(runat), \
+ "i"(IA64_PT_REGS_R16_SLOT): "memory"); \
+} while(0)
-IA64FAULT vcpu_bsw1(VCPU *vcpu)
+IA64FAULT vcpu_bsw1(VCPU * vcpu)
{
// TODO: Only allowed for current vcpu
REGS *regs = vcpu_regs(vcpu);
unsigned long *r = &regs->r16;
- unsigned long *b0 = &PSCB(vcpu,bank0_regs[0]);
- unsigned long *b1 = &PSCB(vcpu,bank1_regs[0]);
+ unsigned long *b0 = &PSCB(vcpu, bank0_regs[0]);
+ unsigned long *b1 = &PSCB(vcpu, bank1_regs[0]);
unsigned long *runat = &regs->eml_unat;
- unsigned long *b0unat = &PSCB(vcpu,vbnat);
- unsigned long *b1unat = &PSCB(vcpu,vnat);
+ unsigned long *b0unat = &PSCB(vcpu, vbnat);
+ unsigned long *b1unat = &PSCB(vcpu, vnat);
unsigned long i;
- if(VMX_DOMAIN(vcpu)){
- if(!(VCPU(vcpu,vpsr)&IA64_PSR_BN)){
- for (i = 0; i < 16; i++) { *b0++ = *r; *r++ = *b1++; }
- vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
- VCPU(vcpu,vpsr) |= IA64_PSR_BN;
- }
- }else{
- if (!PSCB(vcpu,banknum)) {
- for (i = 0; i < 16; i++) { *b0++ = *r; *r++ = *b1++; }
- vcpu_bsw1_unat(i,b0unat,b1unat,runat,IA64_PT_REGS_R16_SLOT);
- PSCB(vcpu,banknum) = 1;
- }
- }
- return (IA64_NO_FAULT);
+ if (VMX_DOMAIN(vcpu)) {
+ if (!(VCPU(vcpu, vpsr) & IA64_PSR_BN)) {
+ for (i = 0; i < 16; i++) {
+ *b0++ = *r;
+ *r++ = *b1++;
+ }
+ vcpu_bsw1_unat(i, b0unat, b1unat, runat,
+ IA64_PT_REGS_R16_SLOT);
+ VCPU(vcpu, vpsr) |= IA64_PSR_BN;
+ }
+ } else {
+ if (!PSCB(vcpu, banknum)) {
+ for (i = 0; i < 16; i++) {
+ *b0++ = *r;
+ *r++ = *b1++;
+ }
+ vcpu_bsw1_unat(i, b0unat, b1unat, runat,
+ IA64_PT_REGS_R16_SLOT);
+ PSCB(vcpu, banknum) = 1;
+ }
+ }
+ return IA64_NO_FAULT;
}
/**************************************************************************
VCPU cpuid access routines
**************************************************************************/
-
-IA64FAULT vcpu_get_cpuid(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval)
{
// FIXME: This could get called as a result of a rsvd-reg fault
// if reg > 3
- switch(reg) {
- case 0:
- memcpy(pval,"Xen/ia64",8);
+ switch (reg) {
+ case 0:
+ memcpy(pval, "Xen/ia64", 8);
break;
- case 1:
+ case 1:
*pval = 0;
break;
- case 2:
+ case 2:
*pval = 0;
break;
- case 3:
+ case 3:
*pval = ia64_get_cpuid(3);
break;
- case 4:
+ case 4:
*pval = ia64_get_cpuid(4);
break;
- default:
+ default:
if (reg > (ia64_get_cpuid(3) & 0xff))
return IA64_RSVDREG_FAULT;
*pval = ia64_get_cpuid(reg);
break;
}
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
/**************************************************************************
VCPU region register access routines
**************************************************************************/
-unsigned long vcpu_get_rr_ve(VCPU *vcpu,UINT64 vadr)
+unsigned long vcpu_get_rr_ve(VCPU * vcpu, u64 vadr)
{
ia64_rr rr;
- rr.rrval = PSCB(vcpu,rrs)[vadr>>61];
- return(rr.ve);
+ rr.rrval = PSCB(vcpu, rrs)[vadr >> 61];
+ return rr.ve;
}
-IA64FAULT vcpu_set_rr(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val)
{
- PSCB(vcpu,rrs)[reg>>61] = val;
+ PSCB(vcpu, rrs)[reg >> 61] = val;
// warning: set_one_rr() does it "live"
- set_one_rr(reg,val);
- return (IA64_NO_FAULT);
+ set_one_rr(reg, val);
+ return IA64_NO_FAULT;
}
-IA64FAULT vcpu_get_rr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval)
{
- if(VMX_DOMAIN(vcpu)){
- *pval = VMX(vcpu,vrr[reg>>61]);
- }else{
- *pval = PSCB(vcpu,rrs)[reg>>61];
- }
- return (IA64_NO_FAULT);
+ if (VMX_DOMAIN(vcpu))
+ *pval = VMX(vcpu, vrr[reg >> 61]);
+ else
+ *pval = PSCB(vcpu, rrs)[reg >> 61];
+
+ return IA64_NO_FAULT;
}
/**************************************************************************
VCPU protection key register access routines
**************************************************************************/
-IA64FAULT vcpu_get_pkr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval)
{
#ifndef PKR_USE_FIXED
printk("vcpu_get_pkr: called, not implemented yet\n");
return IA64_ILLOP_FAULT;
#else
- UINT64 val = (UINT64)ia64_get_pkr(reg);
+ u64 val = (u64) ia64_get_pkr(reg);
*pval = val;
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
#endif
}
-IA64FAULT vcpu_set_pkr(VCPU *vcpu, UINT64 reg, UINT64 val)
+IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val)
{
#ifndef PKR_USE_FIXED
printk("vcpu_set_pkr: called, not implemented yet\n");
return IA64_ILLOP_FAULT;
#else
-// if (reg >= NPKRS) return (IA64_ILLOP_FAULT);
+// if (reg >= NPKRS)
+// return IA64_ILLOP_FAULT;
vcpu->pkrs[reg] = val;
- ia64_set_pkr(reg,val);
- return (IA64_NO_FAULT);
+ ia64_set_pkr(reg, val);
+ return IA64_NO_FAULT;
#endif
}
@@ -1876,21 +2021,22 @@ IA64FAULT vcpu_set_pkr(VCPU *vcpu, UINT64 reg, UINT64 val)
**************************************************************************/
static void
-vcpu_set_tr_entry_rid(TR_ENTRY *trp, UINT64 pte,
- UINT64 itir, UINT64 ifa, UINT64 rid)
+vcpu_set_tr_entry_rid(TR_ENTRY * trp, u64 pte,
+ u64 itir, u64 ifa, u64 rid)
{
- UINT64 ps;
+ u64 ps;
union pte_flags new_pte;
trp->itir = itir;
trp->rid = rid;
ps = trp->ps;
new_pte.val = pte;
- if (new_pte.pl < 2) new_pte.pl = 2;
+ if (new_pte.pl < 2)
+ new_pte.pl = 2;
trp->vadr = ifa & ~0xfff;
- if (ps > 12) { // "ignore" relevant low-order bits
- new_pte.ppn &= ~((1UL<<(ps-12))-1);
- trp->vadr &= ~((1UL<<ps)-1);
+ if (ps > 12) { // "ignore" relevant low-order bits
+ new_pte.ppn &= ~((1UL << (ps - 12)) - 1);
+ trp->vadr &= ~((1UL << ps) - 1);
}
/* Atomic write. */
@@ -1898,25 +2044,26 @@ vcpu_set_tr_entry_rid(TR_ENTRY *trp, UINT64 pte,
}
static inline void
-vcpu_set_tr_entry(TR_ENTRY *trp, UINT64 pte, UINT64 itir, UINT64 ifa)
+vcpu_set_tr_entry(TR_ENTRY * trp, u64 pte, u64 itir, u64 ifa)
{
vcpu_set_tr_entry_rid(trp, pte, itir, ifa,
- VCPU(current, rrs[ifa>>61]) & RR_RID_MASK);
+ VCPU(current, rrs[ifa >> 61]) & RR_RID_MASK);
}
-IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte,
- UINT64 itir, UINT64 ifa)
+IA64FAULT vcpu_itr_d(VCPU * vcpu, u64 slot, u64 pte,
+ u64 itir, u64 ifa)
{
TR_ENTRY *trp;
- if (slot >= NDTRS) return IA64_RSVDREG_FAULT;
+ if (slot >= NDTRS)
+ return IA64_RSVDREG_FAULT;
vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
- trp = &PSCBX(vcpu,dtrs[slot]);
+ trp = &PSCBX(vcpu, dtrs[slot]);
//printf("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
- vcpu_set_tr_entry(trp,pte,itir,ifa);
- vcpu_quick_region_set(PSCBX(vcpu,dtr_regions),ifa);
+ vcpu_set_tr_entry(trp, pte, itir, ifa);
+ vcpu_quick_region_set(PSCBX(vcpu, dtr_regions), ifa);
/*
* FIXME According to spec, vhpt should be purged, but this
@@ -1930,19 +2077,20 @@ IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte,
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_itr_i(VCPU *vcpu, UINT64 slot, UINT64 pte,
- UINT64 itir, UINT64 ifa)
+IA64FAULT vcpu_itr_i(VCPU * vcpu, u64 slot, u64 pte,
+ u64 itir, u64 ifa)
{
TR_ENTRY *trp;
- if (slot >= NITRS) return IA64_RSVDREG_FAULT;
+ if (slot >= NITRS)
+ return IA64_RSVDREG_FAULT;
vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
- trp = &PSCBX(vcpu,itrs[slot]);
+ trp = &PSCBX(vcpu, itrs[slot]);
//printf("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
- vcpu_set_tr_entry(trp,pte,itir,ifa);
- vcpu_quick_region_set(PSCBX(vcpu,itr_regions),ifa);
+ vcpu_set_tr_entry(trp, pte, itir, ifa);
+ vcpu_quick_region_set(PSCBX(vcpu, itr_regions), ifa);
/*
* FIXME According to spec, vhpt should be purged, but this
@@ -1956,13 +2104,13 @@ IA64FAULT vcpu_itr_i(VCPU *vcpu, UINT64 slot, UINT64 pte,
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_itr(VCPU *vcpu, u64 slot, u64 pte,
+IA64FAULT vcpu_set_itr(VCPU * vcpu, u64 slot, u64 pte,
u64 itir, u64 ifa, u64 rid)
{
TR_ENTRY *trp;
if (slot >= NITRS)
- return IA64_RSVDREG_FAULT;
+ return IA64_RSVDREG_FAULT;
trp = &PSCBX(vcpu, itrs[slot]);
vcpu_set_tr_entry_rid(trp, pte, itir, ifa, rid);
@@ -1975,7 +2123,7 @@ IA64FAULT vcpu_set_itr(VCPU *vcpu, u64 slot, u64 pte,
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_set_dtr(VCPU *vcpu, u64 slot, u64 pte,
+IA64FAULT vcpu_set_dtr(VCPU * vcpu, u64 slot, u64 pte,
u64 itir, u64 ifa, u64 rid)
{
TR_ENTRY *trp;
@@ -1998,63 +2146,72 @@ IA64FAULT vcpu_set_dtr(VCPU *vcpu, u64 slot, u64 pte,
VCPU translation cache access routines
**************************************************************************/
-void vcpu_itc_no_srlz(VCPU *vcpu, UINT64 IorD, UINT64 vaddr, UINT64 pte, UINT64 mp_pte, UINT64 logps)
+void
+vcpu_itc_no_srlz(VCPU * vcpu, u64 IorD, u64 vaddr, u64 pte,
+ u64 mp_pte, u64 logps, struct p2m_entry *entry)
{
unsigned long psr;
- unsigned long ps = (vcpu->domain==dom0) ? logps : PAGE_SHIFT;
+ unsigned long ps = (vcpu->domain == dom0) ? logps : PAGE_SHIFT;
- check_xen_space_overlap ("itc", vaddr, 1UL << logps);
+ check_xen_space_overlap("itc", vaddr, 1UL << logps);
// FIXME, must be inlined or potential for nested fault here!
- if ((vcpu->domain==dom0) && (logps < PAGE_SHIFT))
- panic_domain (NULL, "vcpu_itc_no_srlz: domain trying to use "
- "smaller page size!\n");
+ if ((vcpu->domain == dom0) && (logps < PAGE_SHIFT))
+ panic_domain(NULL, "vcpu_itc_no_srlz: domain trying to use "
+ "smaller page size!\n");
BUG_ON(logps > PAGE_SHIFT);
+ vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry);
psr = ia64_clear_ic();
- ia64_itc(IorD,vaddr,pte,ps); // FIXME: look for bigger mappings
+ ia64_itc(IorD, vaddr, pte, ps); // FIXME: look for bigger mappings
ia64_set_psr(psr);
// ia64_srlz_i(); // no srls req'd, will rfi later
#ifdef VHPT_GLOBAL
- if (vcpu->domain==dom0 && ((vaddr >> 61) == 7)) {
+ if (vcpu->domain == dom0 && ((vaddr >> 61) == 7)) {
// FIXME: this is dangerous... vhpt_flush_address ensures these
// addresses never get flushed. More work needed if this
// ever happens.
//printf("vhpt_insert(%p,%p,%p)\n",vaddr,pte,1L<<logps);
- if (logps > PAGE_SHIFT) vhpt_multiple_insert(vaddr,pte,logps);
- else vhpt_insert(vaddr,pte,logps<<2);
+ if (logps > PAGE_SHIFT)
+ vhpt_multiple_insert(vaddr, pte, logps);
+ else
+ vhpt_insert(vaddr, pte, logps << 2);
}
// even if domain pagesize is larger than PAGE_SIZE, just put
// PAGE_SIZE mapping in the vhpt for now, else purging is complicated
- else vhpt_insert(vaddr,pte,PAGE_SHIFT<<2);
+ else
+ vhpt_insert(vaddr, pte, PAGE_SHIFT << 2);
#endif
- if ((mp_pte == -1UL) || (IorD & 0x4)) // don't place in 1-entry TLB
+ if (IorD & 0x4) /* don't place in 1-entry TLB */
return;
if (IorD & 0x1) {
- vcpu_set_tr_entry(&PSCBX(vcpu,itlb),mp_pte,ps<<2,vaddr);
+ vcpu_set_tr_entry(&PSCBX(vcpu, itlb), mp_pte, ps << 2, vaddr);
}
if (IorD & 0x2) {
- vcpu_set_tr_entry(&PSCBX(vcpu,dtlb),mp_pte,ps<<2,vaddr);
+ vcpu_set_tr_entry(&PSCBX(vcpu, dtlb), mp_pte, ps << 2, vaddr);
}
}
-IA64FAULT vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
+IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
{
unsigned long pteval, logps = itir_ps(itir);
- BOOLEAN swap_rr0 = (!(ifa>>61) && PSCB(vcpu,metaphysical_mode));
+ BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
struct p2m_entry entry;
if (logps < PAGE_SHIFT)
- panic_domain (NULL, "vcpu_itc_d: domain trying to use "
- "smaller page size!\n");
+ panic_domain(NULL, "vcpu_itc_d: domain trying to use "
+ "smaller page size!\n");
-again:
+ again:
//itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
- if (!pteval) return IA64_ILLOP_FAULT;
- if (swap_rr0) set_one_rr(0x0,PSCB(vcpu,rrs[0]));
- vcpu_itc_no_srlz(vcpu,2,ifa,pteval,pte,logps);
- if (swap_rr0) set_metaphysical_rr0();
+ if (!pteval)
+ return IA64_ILLOP_FAULT;
+ if (swap_rr0)
+ set_one_rr(0x0, PSCB(vcpu, rrs[0]));
+ vcpu_itc_no_srlz(vcpu, 2, ifa, pteval, pte, logps, &entry);
+ if (swap_rr0)
+ set_metaphysical_rr0();
if (p2m_entry_retry(&entry)) {
vcpu_flush_tlb_vhpt_range(ifa, logps);
goto again;
@@ -2062,22 +2219,25 @@ again:
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
+IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 pte, u64 itir, u64 ifa)
{
unsigned long pteval, logps = itir_ps(itir);
- BOOLEAN swap_rr0 = (!(ifa>>61) && PSCB(vcpu,metaphysical_mode));
+ BOOLEAN swap_rr0 = (!(ifa >> 61) && PSCB(vcpu, metaphysical_mode));
struct p2m_entry entry;
if (logps < PAGE_SHIFT)
- panic_domain (NULL, "vcpu_itc_i: domain trying to use "
- "smaller page size!\n");
-again:
+ panic_domain(NULL, "vcpu_itc_i: domain trying to use "
+ "smaller page size!\n");
+ again:
//itir = (itir & ~0xfc) | (PAGE_SHIFT<<2); // ignore domain's pagesize
pteval = translate_domain_pte(pte, ifa, itir, &logps, &entry);
- if (!pteval) return IA64_ILLOP_FAULT;
- if (swap_rr0) set_one_rr(0x0,PSCB(vcpu,rrs[0]));
- vcpu_itc_no_srlz(vcpu, 1,ifa,pteval,pte,logps);
- if (swap_rr0) set_metaphysical_rr0();
+ if (!pteval)
+ return IA64_ILLOP_FAULT;
+ if (swap_rr0)
+ set_one_rr(0x0, PSCB(vcpu, rrs[0]));
+ vcpu_itc_no_srlz(vcpu, 1, ifa, pteval, pte, logps, &entry);
+ if (swap_rr0)
+ set_metaphysical_rr0();
if (p2m_entry_retry(&entry)) {
vcpu_flush_tlb_vhpt_range(ifa, logps);
goto again;
@@ -2085,18 +2245,18 @@ again:
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 log_range)
+IA64FAULT vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 log_range)
{
BUG_ON(vcpu != current);
- check_xen_space_overlap ("ptc_l", vadr, 1UL << log_range);
+ check_xen_space_overlap("ptc_l", vadr, 1UL << log_range);
/* Purge TC */
- vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb));
- vcpu_purge_tr_entry(&PSCBX(vcpu,itlb));
-
+ vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
+ vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
+
/* Purge all tlb and vhpt */
- vcpu_flush_tlb_vhpt_range (vadr, log_range);
+ vcpu_flush_tlb_vhpt_range(vadr, log_range);
return IA64_NO_FAULT;
}
@@ -2107,13 +2267,13 @@ IA64FAULT vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 log_range)
// access rights fault, we have to translate the virtual address to a
// physical address (possibly via a metaphysical address) and do the fc
// on the physical address, which is guaranteed to flush the same cache line
-IA64FAULT vcpu_fc(VCPU *vcpu, UINT64 vadr)
+IA64FAULT vcpu_fc(VCPU * vcpu, u64 vadr)
{
// TODO: Only allowed for current vcpu
- UINT64 mpaddr, paddr;
+ u64 mpaddr, paddr;
IA64FAULT fault;
-again:
+ again:
fault = vcpu_tpa(vcpu, vadr, &mpaddr);
if (fault == IA64_NO_FAULT) {
struct p2m_entry entry;
@@ -2125,7 +2285,7 @@ again:
return fault;
}
-IA64FAULT vcpu_ptc_e(VCPU *vcpu, UINT64 vadr)
+IA64FAULT vcpu_ptc_e(VCPU * vcpu, u64 vadr)
{
// Note that this only needs to be called once, i.e. the
// architected loop to purge the entire TLB, should use
@@ -2136,27 +2296,27 @@ IA64FAULT vcpu_ptc_e(VCPU *vcpu, UINT64 vadr)
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_ptc_g(VCPU *vcpu, UINT64 vadr, UINT64 addr_range)
+IA64FAULT vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 addr_range)
{
printk("vcpu_ptc_g: called, not implemented yet\n");
return IA64_ILLOP_FAULT;
}
-IA64FAULT vcpu_ptc_ga(VCPU *vcpu,UINT64 vadr,UINT64 addr_range)
+IA64FAULT vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 addr_range)
{
// FIXME: validate not flushing Xen addresses
// if (Xen address) return(IA64_ILLOP_FAULT);
// FIXME: ??breaks if domain PAGE_SIZE < Xen PAGE_SIZE
//printf("######## vcpu_ptc_ga(%p,%p) ##############\n",vadr,addr_range);
- check_xen_space_overlap ("ptc_ga", vadr, addr_range);
+ check_xen_space_overlap("ptc_ga", vadr, addr_range);
- domain_flush_vtlb_range (vcpu->domain, vadr, addr_range);
+ domain_flush_vtlb_range(vcpu->domain, vadr, addr_range);
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
+IA64FAULT vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 log_range)
{
unsigned long region = vadr >> 61;
u64 addr_range = 1UL << log_range;
@@ -2165,29 +2325,30 @@ IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
TR_ENTRY *trp;
BUG_ON(vcpu != current);
- check_xen_space_overlap ("ptr_d", vadr, 1UL << log_range);
+ check_xen_space_overlap("ptr_d", vadr, 1UL << log_range);
- rr = PSCB(vcpu,rrs)[region];
+ rr = PSCB(vcpu, rrs)[region];
rid = rr & RR_RID_MASK;
/* Purge TC */
- vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb));
+ vcpu_purge_tr_entry(&PSCBX(vcpu, dtlb));
/* Purge tr and recompute dtr_regions. */
vcpu->arch.dtr_regions = 0;
for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++)
- if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range))
+ if (vcpu_match_tr_entry_range
+ (trp, rid, vadr, vadr + addr_range))
vcpu_purge_tr_entry(trp);
else if (trp->pte.p)
vcpu_quick_region_set(vcpu->arch.dtr_regions,
trp->vadr);
- vcpu_flush_tlb_vhpt_range (vadr, log_range);
+ vcpu_flush_tlb_vhpt_range(vadr, log_range);
return IA64_NO_FAULT;
}
-IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
+IA64FAULT vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 log_range)
{
unsigned long region = vadr >> 61;
u64 addr_range = 1UL << log_range;
@@ -2196,49 +2357,25 @@ IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 log_range)
TR_ENTRY *trp;
BUG_ON(vcpu != current);
- check_xen_space_overlap ("ptr_i", vadr, 1UL << log_range);
+ check_xen_space_overlap("ptr_i", vadr, 1UL << log_range);
- rr = PSCB(vcpu,rrs)[region];
+ rr = PSCB(vcpu, rrs)[region];
rid = rr & RR_RID_MASK;
/* Purge TC */
- vcpu_purge_tr_entry(&PSCBX(vcpu,itlb));
+ vcpu_purge_tr_entry(&PSCBX(vcpu, itlb));
/* Purge tr and recompute itr_regions. */
vcpu->arch.itr_regions = 0;
for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++)
- if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range))
+ if (vcpu_match_tr_entry_range
+ (trp, rid, vadr, vadr + addr_range))
vcpu_purge_tr_entry(trp);
else if (trp->pte.p)
vcpu_quick_region_set(vcpu->arch.itr_regions,
trp->vadr);
- vcpu_flush_tlb_vhpt_range (vadr, log_range);
+ vcpu_flush_tlb_vhpt_range(vadr, log_range);
return IA64_NO_FAULT;
}
-
-int ia64_map_hypercall_param(void)
-{
- struct vcpu *v = current;
- struct domain *d = current->domain;
- u64 vaddr = v->arch.hypercall_param.va & PAGE_MASK;
- volatile pte_t* pte;
-
- if (v->arch.hypercall_param.va == 0)
- return FALSE;
- pte = lookup_noalloc_domain_pte(d, v->arch.hypercall_param.pa1);
- if (!pte || !pte_present(*pte))
- return FALSE;
- vcpu_itc_no_srlz(v, 2, vaddr, pte_val(*pte), -1UL, PAGE_SHIFT);
- if (v->arch.hypercall_param.pa2) {
- vaddr += PAGE_SIZE;
- pte = lookup_noalloc_domain_pte(d, v->arch.hypercall_param.pa2);
- if (pte && pte_present(*pte)) {
- vcpu_itc_no_srlz(v, 2, vaddr, pte_val(*pte),
- -1UL, PAGE_SHIFT);
- }
- }
- ia64_srlz_d();
- return TRUE;
-}
diff --git a/xen/arch/ia64/xen/vhpt.c b/xen/arch/ia64/xen/vhpt.c
index f8db5c6e17..5b9bd146bc 100644
--- a/xen/arch/ia64/xen/vhpt.c
+++ b/xen/arch/ia64/xen/vhpt.c
@@ -3,6 +3,10 @@
*
* Copyright (C) 2004 Hewlett-Packard Co
* Dan Magenheimer <dan.magenheimer@hp.com>
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ * VA Linux Systems Japan K.K.
+ * per vcpu vhpt support
*/
#include <linux/config.h>
#include <linux/kernel.h>
@@ -14,28 +18,57 @@
#include <asm/page.h>
#include <asm/vhpt.h>
#include <asm/vcpu.h>
+#include <asm/vcpumask.h>
#include <asm/vmmu.h>
/* Defined in tlb.c */
-extern void ia64_global_tlb_purge(UINT64 start, UINT64 end, UINT64 nbits);
+extern void ia64_global_tlb_purge(u64 start, u64 end, u64 nbits);
extern long running_on_sim;
DEFINE_PER_CPU (unsigned long, vhpt_paddr);
DEFINE_PER_CPU (unsigned long, vhpt_pend);
+#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
+DEFINE_PER_CPU(volatile u32, vhpt_tlbflush_timestamp);
+#endif
-void vhpt_flush(void)
+static void
+__vhpt_flush(unsigned long vhpt_maddr)
{
- struct vhpt_lf_entry *v = __va(__ia64_per_cpu_var(vhpt_paddr));
+ struct vhpt_lf_entry *v = (struct vhpt_lf_entry*)__va(vhpt_maddr);
int i;
for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++)
v->ti_tag = INVALID_TI_TAG;
}
-static void vhpt_erase(void)
+void
+local_vhpt_flush(void)
+{
+ /* increment flush clock before flush */
+ u32 flush_time = tlbflush_clock_inc_and_return();
+ __vhpt_flush(__ia64_per_cpu_var(vhpt_paddr));
+ /* this must be after flush */
+ tlbflush_update_time(&__get_cpu_var(vhpt_tlbflush_timestamp),
+ flush_time);
+ perfc_incrc(local_vhpt_flush);
+}
+
+void
+vcpu_vhpt_flush(struct vcpu* v)
{
- struct vhpt_lf_entry *v = (struct vhpt_lf_entry *)VHPT_ADDR;
+ /* increment flush clock before flush */
+ u32 flush_time = tlbflush_clock_inc_and_return();
+ __vhpt_flush(vcpu_vhpt_maddr(v));
+ /* this must be after flush */
+ tlbflush_update_time(&v->arch.tlbflush_timestamp, flush_time);
+ perfc_incrc(vcpu_vhpt_flush);
+}
+
+static void
+vhpt_erase(unsigned long vhpt_maddr)
+{
+ struct vhpt_lf_entry *v = (struct vhpt_lf_entry*)__va(vhpt_maddr);
int i;
for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++) {
@@ -47,17 +80,6 @@ static void vhpt_erase(void)
// initialize cache too???
}
-
-static void vhpt_map(unsigned long pte)
-{
- unsigned long psr;
-
- psr = ia64_clear_ic();
- ia64_itr(0x2, IA64_TR_VHPT, VHPT_ADDR, pte, VHPT_SIZE_LOG2);
- ia64_set_psr(psr);
- ia64_srlz_i();
-}
-
void vhpt_insert (unsigned long vadr, unsigned long pte, unsigned long logps)
{
struct vhpt_lf_entry *vlfe = (struct vhpt_lf_entry *)ia64_thash(vadr);
@@ -102,7 +124,7 @@ void vhpt_multiple_insert(unsigned long vaddr, unsigned long pte, unsigned long
void vhpt_init(void)
{
- unsigned long paddr, pte;
+ unsigned long paddr;
struct page_info *page;
#if !VHPT_ENABLED
return;
@@ -122,14 +144,83 @@ void vhpt_init(void)
__get_cpu_var(vhpt_pend) = paddr + (1 << VHPT_SIZE_LOG2) - 1;
printf("vhpt_init: vhpt paddr=0x%lx, end=0x%lx\n",
paddr, __get_cpu_var(vhpt_pend));
- pte = pte_val(pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL));
- vhpt_map(pte);
- ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
- VHPT_ENABLED);
- vhpt_erase();
+ vhpt_erase(paddr);
+ // we don't enable VHPT here.
+ // context_switch() or schedule_tail() does it.
+}
+
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+int
+pervcpu_vhpt_alloc(struct vcpu *v)
+{
+ unsigned long vhpt_size_log2 = VHPT_SIZE_LOG2;
+
+ v->arch.vhpt_entries =
+ (1UL << vhpt_size_log2) / sizeof(struct vhpt_lf_entry);
+ v->arch.vhpt_page =
+ alloc_domheap_pages(NULL, vhpt_size_log2 - PAGE_SHIFT, 0);
+ if (!v->arch.vhpt_page)
+ return -ENOMEM;
+
+ v->arch.vhpt_maddr = page_to_maddr(v->arch.vhpt_page);
+ if (v->arch.vhpt_maddr & ((1 << VHPT_SIZE_LOG2) - 1))
+ panic("pervcpu_vhpt_init: bad VHPT alignment!\n");
+
+ v->arch.pta.val = 0; // to zero reserved bits
+ v->arch.pta.ve = 1; // enable vhpt
+ v->arch.pta.size = VHPT_SIZE_LOG2;
+ v->arch.pta.vf = 1; // long format
+ v->arch.pta.base = __va_ul(v->arch.vhpt_maddr) >> 15;
+
+ vhpt_erase(v->arch.vhpt_maddr);
+ smp_mb(); // per vcpu vhpt may be used by another physical cpu.
+ return 0;
}
+void
+pervcpu_vhpt_free(struct vcpu *v)
+{
+ free_domheap_pages(v->arch.vhpt_page, VHPT_SIZE_LOG2 - PAGE_SHIFT);
+}
+#endif
+
+void
+domain_purge_swtc_entries(struct domain *d)
+{
+ struct vcpu* v;
+ for_each_vcpu(d, v) {
+ if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
+ continue;
+
+ /* Purge TC entries.
+ FIXME: clear only if match. */
+ vcpu_purge_tr_entry(&PSCBX(v,dtlb));
+ vcpu_purge_tr_entry(&PSCBX(v,itlb));
+ }
+}
+
+void
+domain_purge_swtc_entries_vcpu_dirty_mask(struct domain* d,
+ vcpumask_t vcpu_dirty_mask)
+{
+ int vcpu;
+
+ for_each_vcpu_mask(vcpu, vcpu_dirty_mask) {
+ struct vcpu* v = d->vcpu[vcpu];
+ if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
+ continue;
+
+ /* Purge TC entries.
+ FIXME: clear only if match. */
+ vcpu_purge_tr_entry(&PSCBX(v, dtlb));
+ vcpu_purge_tr_entry(&PSCBX(v, itlb));
+ }
+}
+// SMP: we can't assume v == current, vcpu might move to another physical cpu.
+// So memory barrier is necessary.
+// if we can guranttee that vcpu can run on only this physical cpu
+// (e.g. vcpu == current), smp_mb() is unnecessary.
void vcpu_flush_vtlb_all(struct vcpu *v)
{
if (VMX_DOMAIN(v)) {
@@ -137,6 +228,7 @@ void vcpu_flush_vtlb_all(struct vcpu *v)
grant_table share page from guest_physmap_remove_page()
in arch_memory_op() XENMEM_add_to_physmap to realize
PV-on-HVM feature. */
+ /* FIXME: This is not SMP-safe yet about p2m table */
/* Purge vTLB for VT-i domain */
thash_purge_all(v);
}
@@ -144,9 +236,14 @@ void vcpu_flush_vtlb_all(struct vcpu *v)
/* First VCPU tlb. */
vcpu_purge_tr_entry(&PSCBX(v,dtlb));
vcpu_purge_tr_entry(&PSCBX(v,itlb));
+ smp_mb();
/* Then VHPT. */
- vhpt_flush();
+ if (HAS_PERVCPU_VHPT(v->domain))
+ vcpu_vhpt_flush(v);
+ else
+ local_vhpt_flush();
+ smp_mb();
/* Then mTLB. */
local_flush_tlb_all();
@@ -155,6 +252,8 @@ void vcpu_flush_vtlb_all(struct vcpu *v)
/* We could clear bit in d->domain_dirty_cpumask only if domain d in
not running on this processor. There is currently no easy way to
check this. */
+
+ perfc_incrc(vcpu_flush_vtlb_all);
}
static void __vcpu_flush_vtlb_all(void *vcpu)
@@ -174,32 +273,60 @@ void domain_flush_vtlb_all (void)
if (v->processor == cpu)
vcpu_flush_vtlb_all(v);
else
+ // SMP: it is racy to reference v->processor.
+ // vcpu scheduler may move this vcpu to another
+ // physicall processor, and change the value
+ // using plain store.
+ // We may be seeing the old value of it.
+ // In such case, flush_vtlb_for_context_switch()
+ // takes care of mTLB flush.
smp_call_function_single(v->processor,
__vcpu_flush_vtlb_all,
v, 1, 1);
}
+ perfc_incrc(domain_flush_vtlb_all);
}
-static void cpu_flush_vhpt_range (int cpu, u64 vadr, u64 addr_range)
+// Callers may need to call smp_mb() before/after calling this.
+// Be carefull.
+static void
+__flush_vhpt_range(unsigned long vhpt_maddr, u64 vadr, u64 addr_range)
{
- void *vhpt_base = __va(per_cpu(vhpt_paddr, cpu));
+ void *vhpt_base = __va(vhpt_maddr);
while ((long)addr_range > 0) {
/* Get the VHPT entry. */
- unsigned int off = ia64_thash(vadr) - VHPT_ADDR;
- volatile struct vhpt_lf_entry *v;
- v = vhpt_base + off;
+ unsigned int off = ia64_thash(vadr) -
+ __va_ul(vcpu_vhpt_maddr(current));
+ struct vhpt_lf_entry *v = vhpt_base + off;
v->ti_tag = INVALID_TI_TAG;
addr_range -= PAGE_SIZE;
vadr += PAGE_SIZE;
}
}
+static void
+cpu_flush_vhpt_range(int cpu, u64 vadr, u64 addr_range)
+{
+ __flush_vhpt_range(per_cpu(vhpt_paddr, cpu), vadr, addr_range);
+}
+
+static void
+vcpu_flush_vhpt_range(struct vcpu* v, u64 vadr, u64 addr_range)
+{
+ __flush_vhpt_range(vcpu_vhpt_maddr(v), vadr, addr_range);
+}
+
void vcpu_flush_tlb_vhpt_range (u64 vadr, u64 log_range)
{
- cpu_flush_vhpt_range (current->processor, vadr, 1UL << log_range);
+ if (HAS_PERVCPU_VHPT(current->domain))
+ vcpu_flush_vhpt_range(current, vadr, 1UL << log_range);
+ else
+ cpu_flush_vhpt_range(current->processor,
+ vadr, 1UL << log_range);
ia64_ptcl(vadr, log_range << 2);
ia64_srlz_i();
+ perfc_incrc(vcpu_flush_tlb_vhpt_range);
}
void domain_flush_vtlb_range (struct domain *d, u64 vadr, u64 addr_range)
@@ -214,34 +341,133 @@ void domain_flush_vtlb_range (struct domain *d, u64 vadr, u64 addr_range)
}
#endif
- for_each_vcpu (d, v) {
- if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
- continue;
-
- /* Purge TC entries.
- FIXME: clear only if match. */
- vcpu_purge_tr_entry(&PSCBX(v,dtlb));
- vcpu_purge_tr_entry(&PSCBX(v,itlb));
- }
+ domain_purge_swtc_entries(d);
smp_mb();
for_each_vcpu (d, v) {
if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
continue;
- /* Invalidate VHPT entries. */
- cpu_flush_vhpt_range (v->processor, vadr, addr_range);
+ if (HAS_PERVCPU_VHPT(d)) {
+ vcpu_flush_vhpt_range(v, vadr, addr_range);
+ } else {
+ // SMP: it is racy to reference v->processor.
+ // vcpu scheduler may move this vcpu to another
+ // physicall processor, and change the value
+ // using plain store.
+ // We may be seeing the old value of it.
+ // In such case, flush_vtlb_for_context_switch()
+ /* Invalidate VHPT entries. */
+ cpu_flush_vhpt_range(v->processor, vadr, addr_range);
+ }
}
// ptc.ga has release semantics.
/* ptc.ga */
ia64_global_tlb_purge(vadr,vadr+addr_range,PAGE_SHIFT);
+ perfc_incrc(domain_flush_vtlb_range);
}
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+#include <asm/tlb_track.h>
+#include <asm/vmx_vcpu.h>
+void
+__domain_flush_vtlb_track_entry(struct domain* d,
+ const struct tlb_track_entry* entry)
+{
+ unsigned long rr7_rid;
+ int swap_rr0 = 0;
+ unsigned long old_rid;
+ unsigned long vaddr = entry->vaddr;
+ struct vcpu* v;
+ int cpu;
+ int vcpu;
+ int local_purge = 1;
+
+ BUG_ON((vaddr >> VRN_SHIFT) != VRN7);
+ /*
+ * heuristic:
+ * dom0linux accesses grant mapped pages via the kernel
+ * straight mapped area and it doesn't change rr7 rid.
+ * So it is likey that rr7 == entry->rid so that
+ * we can avoid rid change.
+ * When blktap is supported, this heuristic should be revised.
+ */
+ vcpu_get_rr(current, VRN7 << VRN_SHIFT, &rr7_rid);
+ if (likely(rr7_rid == entry->rid)) {
+ perfc_incrc(tlb_track_use_rr7);
+ } else {
+ swap_rr0 = 1;
+ vaddr = (vaddr << 3) >> 3;// force vrn0
+ perfc_incrc(tlb_track_swap_rr0);
+ }
+
+ // tlb_track_entry_printf(entry);
+ if (swap_rr0) {
+ vcpu_get_rr(current, 0, &old_rid);
+ vcpu_set_rr(current, 0, entry->rid);
+ }
+
+ if (HAS_PERVCPU_VHPT(d)) {
+ for_each_vcpu_mask(vcpu, entry->vcpu_dirty_mask) {
+ v = d->vcpu[vcpu];
+ if (!test_bit(_VCPUF_initialised, &v->vcpu_flags))
+ continue;
+
+ /* Invalidate VHPT entries. */
+ vcpu_flush_vhpt_range(v, vaddr, PAGE_SIZE);
+
+ /*
+ * current->processor == v->processor
+ * is racy. we may see old v->processor and
+ * a new physical processor of v might see old
+ * vhpt entry and insert tlb.
+ */
+ if (v != current)
+ local_purge = 0;
+ }
+ } else {
+ for_each_cpu_mask(cpu, entry->pcpu_dirty_mask) {
+ /* Invalidate VHPT entries. */
+ cpu_flush_vhpt_range(cpu, vaddr, PAGE_SIZE);
+
+ if (d->vcpu[cpu] != current)
+ local_purge = 0;
+ }
+ }
+
+ /* ptc.ga */
+ if (local_purge) {
+ ia64_ptcl(vaddr, PAGE_SHIFT << 2);
+ perfc_incrc(domain_flush_vtlb_local);
+ } else {
+ /* ptc.ga has release semantics. */
+ ia64_global_tlb_purge(vaddr, vaddr + PAGE_SIZE, PAGE_SHIFT);
+ perfc_incrc(domain_flush_vtlb_global);
+ }
+
+ if (swap_rr0) {
+ vcpu_set_rr(current, 0, old_rid);
+ }
+ perfc_incrc(domain_flush_vtlb_track_entry);
+}
+
+void
+domain_flush_vtlb_track_entry(struct domain* d,
+ const struct tlb_track_entry* entry)
+{
+ domain_purge_swtc_entries_vcpu_dirty_mask(d, entry->vcpu_dirty_mask);
+ smp_mb();
+
+ __domain_flush_vtlb_track_entry(d, entry);
+}
+
+#endif
+
static void flush_tlb_vhpt_all (struct domain *d)
{
/* First VHPT. */
- vhpt_flush ();
+ local_vhpt_flush ();
/* Then mTLB. */
local_flush_tlb_all ();
@@ -250,7 +476,10 @@ static void flush_tlb_vhpt_all (struct domain *d)
void domain_flush_tlb_vhpt(struct domain *d)
{
/* Very heavy... */
- on_each_cpu ((void (*)(void *))flush_tlb_vhpt_all, d, 1, 1);
+ if (HAS_PERVCPU_VHPT(d) || d->arch.is_vti)
+ on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1);
+ else
+ on_each_cpu((void (*)(void *))flush_tlb_vhpt_all, d, 1, 1);
cpus_clear (d->domain_dirty_cpumask);
}
diff --git a/xen/arch/ia64/xen/xen.lds.S b/xen/arch/ia64/xen/xen.lds.S
index 3884f80679..96cd1ce14f 100644
--- a/xen/arch/ia64/xen/xen.lds.S
+++ b/xen/arch/ia64/xen/xen.lds.S
@@ -173,6 +173,9 @@ SECTIONS
* kernel data
*/
+ .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET)
+ { *(.data.read_mostly) }
+
.data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET)
{ *(.data.cacheline_aligned) }
diff --git a/xen/arch/ia64/xen/xenasm.S b/xen/arch/ia64/xen/xenasm.S
index 0f0cff9620..af5f31c5b2 100644
--- a/xen/arch/ia64/xen/xenasm.S
+++ b/xen/arch/ia64/xen/xenasm.S
@@ -26,10 +26,11 @@
// void *shared_info, /* in1 */
// void *shared_arch_info, /* in2 */
// unsigned long shared_info_va, /* in3 */
-// unsigned long p_vhpt) /* in4 */
+// unsigned long va_vhpt) /* in4 */
//Local usage:
// loc0=rp, loc1=ar.pfs, loc2=percpu_paddr, loc3=psr, loc4=ar.rse
// loc5=pal_vaddr, loc6=xen_paddr, loc7=shared_archinfo_paddr,
+// r16, r19, r20 are used by ia64_switch_mode_{phys, virt}()
GLOBAL_ENTRY(ia64_new_rr7)
// FIXME? not sure this unwind statement is correct...
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1)
@@ -118,16 +119,31 @@ GLOBAL_ENTRY(ia64_new_rr7)
// VHPT
#if VHPT_ENABLED
- mov r24=VHPT_SIZE_LOG2<<2
- movl r22=VHPT_ADDR
+#if IA64_GRANULE_SHIFT < VHPT_SIZE_LOG2
+#error "it must be that VHPT_SIZE_LOG2 <= IA64_GRANULE_SHIFT"
+#endif
+ // unless overlaps with KERNEL_TR and IA64_TR_CURRENT_STACK
+ dep r14=0,in4,0,KERNEL_TR_PAGE_SHIFT
+ dep r15=0,in4,0,IA64_GRANULE_SHIFT
+ dep r21=0,r13,0,IA64_GRANULE_SHIFT
+ ;;
+ cmp.eq p7,p0=r17,r14
+ cmp.eq p8,p0=r15,r21
+(p7) br.cond.sptk .vhpt_overlaps
+(p8) br.cond.sptk .vhpt_overlaps
mov r21=IA64_TR_VHPT
+ dep r22=0,r15,60,4 // physical address of
+ // va_vhpt & ~(IA64_GRANULE_SIZE - 1)
+ mov r24=IA64_GRANULE_SHIFT<<2
;;
- ptr.d r22,r24
- or r23=in4,r26 // construct PA | page properties
+ ptr.d r15,r24
+ or r23=r22,r26 // construct PA | page properties
mov cr.itir=r24
- mov cr.ifa=r22
+ mov cr.ifa=r15
+ srlz.d
;;
itr.d dtr[r21]=r23 // wire in new mapping...
+.vhpt_overlaps:
#endif
// Shared info
diff --git a/xen/arch/ia64/xen/xencomm.c b/xen/arch/ia64/xen/xencomm.c
new file mode 100644
index 0000000000..a13eeff1fc
--- /dev/null
+++ b/xen/arch/ia64/xen/xencomm.c
@@ -0,0 +1,380 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ * Tristan Gingold <tristan.gingold@bull.net>
+ */
+
+#include <xen/config.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <asm/current.h>
+#include <asm/guest_access.h>
+#include <public/xen.h>
+#include <public/xencomm.h>
+#include <xen/errno.h>
+
+#undef DEBUG
+#ifdef DEBUG
+static int xencomm_debug = 1; /* extremely verbose */
+#else
+#define xencomm_debug 0
+#endif
+
+static int
+xencomm_copy_chunk_from(
+ unsigned long to,
+ unsigned long paddr,
+ unsigned int len)
+{
+ unsigned long maddr;
+ struct page_info *page;
+
+ while (1) {
+ maddr = xencomm_paddr_to_maddr(paddr);
+ if (xencomm_debug > 1)
+ printk("%lx[%d] -> %lx\n", maddr, len, to);
+ if (maddr == 0)
+ return -EFAULT;
+
+ page = virt_to_page(maddr);
+ if (get_page(page, current->domain) == 0) {
+ if (page_get_owner(page) != current->domain) {
+ /* This page might be a page granted by another domain */
+ panic_domain(NULL, "copy_from_guest from foreign domain\n");
+ }
+ /* Try again. */
+ continue;
+ }
+ memcpy((void *)to, (void *)maddr, len);
+ put_page(page);
+ return 0;
+ }
+}
+
+/**
+ * xencomm_copy_from_guest: Copy a block of data from domain space.
+ * @to: Machine address.
+ * @from: Physical address to a xencomm buffer descriptor.
+ * @n: Number of bytes to copy.
+ * @skip: Number of bytes from the start to skip.
+ *
+ * Copy data from domain to hypervisor.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long
+xencomm_copy_from_guest(
+ void *to,
+ const void *from,
+ unsigned int n,
+ unsigned int skip)
+{
+ struct xencomm_desc *desc;
+ unsigned long desc_addr;
+ unsigned int from_pos = 0;
+ unsigned int to_pos = 0;
+ unsigned int i = 0;
+
+ if (xencomm_debug)
+ printf("xencomm_copy_from_guest: from=%lx+%u n=%u\n",
+ (unsigned long)from, skip, n);
+
+ if (XENCOMM_IS_INLINE(from)) {
+ unsigned long src_paddr = XENCOMM_INLINE_ADDR(from);
+
+ src_paddr += skip;
+
+ while (n > 0) {
+ unsigned int chunksz;
+ unsigned int bytes;
+ int res;
+
+ chunksz = PAGE_SIZE - (src_paddr % PAGE_SIZE);
+
+ bytes = min(chunksz, n);
+
+ res = xencomm_copy_chunk_from((unsigned long)to, src_paddr, bytes);
+ if (res != 0)
+ return -EFAULT;
+ src_paddr += bytes;
+ to += bytes;
+ n -= bytes;
+ }
+
+ /* Always successful. */
+ return 0;
+ }
+
+ /* first we need to access the descriptor */
+ desc_addr = xencomm_paddr_to_maddr((unsigned long)from);
+ if (desc_addr == 0)
+ return -EFAULT;
+
+ desc = (struct xencomm_desc *)desc_addr;
+ if (desc->magic != XENCOMM_MAGIC) {
+ printk("%s: error: %p magic was 0x%x\n",
+ __func__, desc, desc->magic);
+ return -EFAULT;
+ }
+
+ /* iterate through the descriptor, copying up to a page at a time */
+ while ((to_pos < n) && (i < desc->nr_addrs)) {
+ unsigned long src_paddr = desc->address[i];
+ unsigned int pgoffset;
+ unsigned int chunksz;
+ unsigned int chunk_skip;
+
+ if (src_paddr == XENCOMM_INVALID) {
+ i++;
+ continue;
+ }
+
+ pgoffset = src_paddr % PAGE_SIZE;
+ chunksz = PAGE_SIZE - pgoffset;
+
+ chunk_skip = min(chunksz, skip);
+ from_pos += chunk_skip;
+ chunksz -= chunk_skip;
+ skip -= chunk_skip;
+
+ if (skip == 0) {
+ unsigned int bytes = min(chunksz, n - to_pos);
+ int res;
+
+ if (xencomm_debug > 1)
+ printf ("src_paddr=%lx i=%d, skip=%d\n",
+ src_paddr, i, chunk_skip);
+
+ res = xencomm_copy_chunk_from((unsigned long)to + to_pos,
+ src_paddr + chunk_skip, bytes);
+ if (res != 0)
+ return -EFAULT;
+
+ from_pos += bytes;
+ to_pos += bytes;
+ }
+
+ i++;
+ }
+
+ return n - to_pos;
+}
+
+static int
+xencomm_copy_chunk_to(
+ unsigned long paddr,
+ unsigned long from,
+ unsigned int len)
+{
+ unsigned long maddr;
+ struct page_info *page;
+
+ while (1) {
+ maddr = xencomm_paddr_to_maddr(paddr);
+ if (xencomm_debug > 1)
+ printk("%lx[%d] -> %lx\n", from, len, maddr);
+ if (maddr == 0)
+ return -EFAULT;
+
+ page = virt_to_page(maddr);
+ if (get_page(page, current->domain) == 0) {
+ if (page_get_owner(page) != current->domain) {
+ /* This page might be a page granted by another domain */
+ panic_domain(NULL, "copy_to_guest to foreign domain\n");
+ }
+ /* Try again. */
+ continue;
+ }
+ memcpy((void *)maddr, (void *)from, len);
+ put_page(page);
+ return 0;
+ }
+}
+
+/**
+ * xencomm_copy_to_guest: Copy a block of data to domain space.
+ * @to: Physical address to xencomm buffer descriptor.
+ * @from: Machine address.
+ * @n: Number of bytes to copy.
+ * @skip: Number of bytes from the start to skip.
+ *
+ * Copy data from hypervisor to domain.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long
+xencomm_copy_to_guest(
+ void *to,
+ const void *from,
+ unsigned int n,
+ unsigned int skip)
+{
+ struct xencomm_desc *desc;
+ unsigned long desc_addr;
+ unsigned int from_pos = 0;
+ unsigned int to_pos = 0;
+ unsigned int i = 0;
+
+ if (xencomm_debug)
+ printf ("xencomm_copy_to_guest: to=%lx+%u n=%u\n",
+ (unsigned long)to, skip, n);
+
+ if (XENCOMM_IS_INLINE(to)) {
+ unsigned long dest_paddr = XENCOMM_INLINE_ADDR(to);
+
+ dest_paddr += skip;
+
+ while (n > 0) {
+ unsigned int chunksz;
+ unsigned int bytes;
+ int res;
+
+ chunksz = PAGE_SIZE - (dest_paddr % PAGE_SIZE);
+
+ bytes = min(chunksz, n);
+
+ res = xencomm_copy_chunk_to(dest_paddr, (unsigned long)from, bytes);
+ if (res != 0)
+ return res;
+
+ dest_paddr += bytes;
+ from += bytes;
+ n -= bytes;
+ }
+
+ /* Always successful. */
+ return 0;
+ }
+
+ /* first we need to access the descriptor */
+ desc_addr = xencomm_paddr_to_maddr((unsigned long)to);
+ if (desc_addr == 0)
+ return -EFAULT;
+
+ desc = (struct xencomm_desc *)desc_addr;
+ if (desc->magic != XENCOMM_MAGIC) {
+ printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+ return -EFAULT;
+ }
+
+ /* iterate through the descriptor, copying up to a page at a time */
+ while ((from_pos < n) && (i < desc->nr_addrs)) {
+ unsigned long dest_paddr = desc->address[i];
+ unsigned int pgoffset;
+ unsigned int chunksz;
+ unsigned int chunk_skip;
+
+ if (dest_paddr == XENCOMM_INVALID) {
+ i++;
+ continue;
+ }
+
+ pgoffset = dest_paddr % PAGE_SIZE;
+ chunksz = PAGE_SIZE - pgoffset;
+
+ chunk_skip = min(chunksz, skip);
+ to_pos += chunk_skip;
+ chunksz -= chunk_skip;
+ skip -= chunk_skip;
+ dest_paddr += chunk_skip;
+
+ if (skip == 0) {
+ unsigned int bytes = min(chunksz, n - from_pos);
+ int res;
+
+ res = xencomm_copy_chunk_to(dest_paddr,
+ (unsigned long)from + from_pos, bytes);
+ if (res != 0)
+ return res;
+
+ from_pos += bytes;
+ to_pos += bytes;
+ }
+
+ i++;
+ }
+ return n - from_pos;
+}
+
+/* Offset page addresses in 'handle' to skip 'bytes' bytes. Set completely
+ * exhausted pages to XENCOMM_INVALID. */
+void *
+xencomm_add_offset(
+ void *handle,
+ unsigned int bytes)
+{
+ struct xencomm_desc *desc;
+ unsigned long desc_addr;
+ int i = 0;
+
+ if (XENCOMM_IS_INLINE(handle))
+ return (void *)((unsigned long)handle + bytes);
+
+ /* first we need to access the descriptor */
+ desc_addr = xencomm_paddr_to_maddr((unsigned long)handle);
+ if (desc_addr == 0)
+ return NULL;
+
+ desc = (struct xencomm_desc *)desc_addr;
+ if (desc->magic != XENCOMM_MAGIC) {
+ printk("%s error: %p magic was 0x%x\n", __func__, desc, desc->magic);
+ return NULL;
+ }
+
+ /* iterate through the descriptor incrementing addresses */
+ while ((bytes > 0) && (i < desc->nr_addrs)) {
+ unsigned long dest_paddr = desc->address[i];
+ unsigned int pgoffset;
+ unsigned int chunksz;
+ unsigned int chunk_skip;
+
+ pgoffset = dest_paddr % PAGE_SIZE;
+ chunksz = PAGE_SIZE - pgoffset;
+
+ chunk_skip = min(chunksz, bytes);
+ if (chunk_skip == chunksz) {
+ /* exhausted this page */
+ desc->address[i] = XENCOMM_INVALID;
+ } else {
+ desc->address[i] += chunk_skip;
+ }
+ bytes -= chunk_skip;
+ }
+ return handle;
+}
+
+int
+xencomm_handle_is_null(
+ void *ptr)
+{
+ if (XENCOMM_IS_INLINE(ptr))
+ return XENCOMM_INLINE_ADDR(ptr) == 0;
+ else {
+ struct xencomm_desc *desc;
+ unsigned long desc_addr;
+
+ desc_addr = xencomm_paddr_to_maddr((unsigned long)ptr);
+ if (desc_addr == 0)
+ return 1;
+
+ desc = (struct xencomm_desc *)desc_addr;
+ return (desc->address[0] == XENCOMM_INVALID);
+ }
+}
diff --git a/xen/arch/ia64/xen/xenmem.c b/xen/arch/ia64/xen/xenmem.c
index 49b6c55588..c837f0fb4b 100644
--- a/xen/arch/ia64/xen/xenmem.c
+++ b/xen/arch/ia64/xen/xenmem.c
@@ -17,10 +17,19 @@
#include <linux/efi.h>
#include <asm/pgalloc.h>
-extern pgd_t frametable_pg_dir[];
+extern unsigned long frametable_pg_dir[];
-#define frametable_pgd_offset(addr) \
- (frametable_pg_dir + (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)))
+#define FRAMETABLE_PGD_OFFSET(ADDR) \
+ (frametable_pg_dir + (((ADDR) >> PGDIR_SHIFT) & \
+ ((1UL << (PAGE_SHIFT - 3)) - 1)))
+
+#define FRAMETABLE_PMD_OFFSET(PGD, ADDR) \
+ __va((unsigned long *)(PGD) + (((ADDR) >> PMD_SHIFT) & \
+ ((1UL << (PAGE_SHIFT - 3)) - 1)))
+
+#define FRAMETABLE_PTE_OFFSET(PMD, ADDR) \
+ (pte_t *)__va((unsigned long *)(PMD) + (((ADDR) >> PAGE_SHIFT) & \
+ ((1UL << (PAGE_SHIFT - 3)) - 1)))
static unsigned long table_size;
static int opt_contig_mem = 0;
@@ -29,13 +38,13 @@ boolean_param("contig_mem", opt_contig_mem);
#define opt_contig_mem 1
#endif
-struct page_info *frame_table;
+struct page_info *frame_table __read_mostly;
unsigned long max_page;
/*
* Set up the page tables.
*/
-volatile unsigned long *mpt_table;
+volatile unsigned long *mpt_table __read_mostly;
void
paging_init (void)
@@ -72,7 +81,7 @@ paging_init (void)
#ifdef CONFIG_VIRTUAL_FRAME_TABLE
-static inline void *
+static unsigned long
alloc_dir_page(void)
{
unsigned long mfn = alloc_boot_pages(1, 1);
@@ -82,7 +91,7 @@ alloc_dir_page(void)
++table_size;
dir = mfn << PAGE_SHIFT;
memset(__va(dir), 0, PAGE_SIZE);
- return (void *)dir;
+ return dir;
}
static inline unsigned long
@@ -100,15 +109,33 @@ alloc_table_page(unsigned long fill)
return mfn;
}
+static void
+create_page_table(unsigned long start_page, unsigned long end_page,
+ unsigned long fill)
+{
+ unsigned long address;
+ unsigned long *dir;
+ pte_t *pteptr;
+
+ for (address = start_page; address < end_page; address += PAGE_SIZE) {
+ dir = FRAMETABLE_PGD_OFFSET(address);
+ if (!*dir)
+ *dir = alloc_dir_page();
+ dir = FRAMETABLE_PMD_OFFSET(*dir, address);
+ if (!*dir)
+ *dir = alloc_dir_page();
+ pteptr = FRAMETABLE_PTE_OFFSET(*dir, address);
+ if (pte_none(*pteptr))
+ set_pte(pteptr, pfn_pte(alloc_table_page(fill),
+ PAGE_KERNEL));
+ }
+}
+
static int
create_frametable_page_table (u64 start, u64 end, void *arg)
{
- unsigned long address, start_page, end_page;
struct page_info *map_start, *map_end;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
+ unsigned long start_page, end_page;
map_start = frame_table + (__pa(start) >> PAGE_SHIFT);
map_end = frame_table + (__pa(end) >> PAGE_SHIFT);
@@ -116,23 +143,7 @@ create_frametable_page_table (u64 start, u64 end, void *arg)
start_page = (unsigned long) map_start & PAGE_MASK;
end_page = PAGE_ALIGN((unsigned long) map_end);
- for (address = start_page; address < end_page; address += PAGE_SIZE) {
- pgd = frametable_pgd_offset(address);
- if (pgd_none(*pgd))
- pgd_populate(NULL, pgd, alloc_dir_page());
- pud = pud_offset(pgd, address);
-
- if (pud_none(*pud))
- pud_populate(NULL, pud, alloc_dir_page());
- pmd = pmd_offset(pud, address);
-
- if (pmd_none(*pmd))
- pmd_populate_kernel(NULL, pmd, alloc_dir_page());
- pte = pte_offset_kernel(pmd, address);
-
- if (pte_none(*pte))
- set_pte(pte, pfn_pte(alloc_table_page(0), PAGE_KERNEL));
- }
+ create_page_table(start_page, end_page, 0L);
return 0;
}
@@ -140,11 +151,7 @@ static int
create_mpttable_page_table (u64 start, u64 end, void *arg)
{
unsigned long map_start, map_end;
- unsigned long address, start_page, end_page;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
+ unsigned long start_page, end_page;
map_start = (unsigned long)(mpt_table + (__pa(start) >> PAGE_SHIFT));
map_end = (unsigned long)(mpt_table + (__pa(end) >> PAGE_SHIFT));
@@ -152,23 +159,7 @@ create_mpttable_page_table (u64 start, u64 end, void *arg)
start_page = map_start & PAGE_MASK;
end_page = PAGE_ALIGN(map_end);
- for (address = start_page; address < end_page; address += PAGE_SIZE) {
- pgd = frametable_pgd_offset(address);
- if (pgd_none(*pgd))
- pgd_populate(NULL, pgd, alloc_dir_page());
- pud = pud_offset(pgd, address);
-
- if (pud_none(*pud))
- pud_populate(NULL, pud, alloc_dir_page());
- pmd = pmd_offset(pud, address);
-
- if (pmd_none(*pmd))
- pmd_populate_kernel(NULL, pmd, alloc_dir_page());
- pte = pte_offset_kernel(pmd, address);
-
- if (pte_none(*pte))
- set_pte(pte, pfn_pte(alloc_table_page(INVALID_M2P_ENTRY), PAGE_KERNEL));
- }
+ create_page_table(start_page, end_page, INVALID_M2P_ENTRY);
return 0;
}
diff --git a/xen/arch/ia64/xen/xenpatch.c b/xen/arch/ia64/xen/xenpatch.c
new file mode 100644
index 0000000000..561e48d28e
--- /dev/null
+++ b/xen/arch/ia64/xen/xenpatch.c
@@ -0,0 +1,122 @@
+/******************************************************************************
+ * xenpatch.c
+ * Copyright (c) 2006 Silicon Graphics Inc.
+ * Jes Sorensen <jes@sgi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Parts of this based on code from arch/ia64/kernel/patch.c
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <asm/xensystem.h>
+#include <asm/intrinsics.h>
+
+/*
+ * This was adapted from code written by Tony Luck:
+ *
+ * The 64-bit value in a "movl reg=value" is scattered between the two words of the bundle
+ * like this:
+ *
+ * 6 6 5 4 3 2 1
+ * 3210987654321098765432109876543210987654321098765432109876543210
+ * ABBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCDEEEEEFFFFFFFFFGGGGGGG
+ *
+ * CCCCCCCCCCCCCCCCCCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ * xxxxAFFFFFFFFFEEEEEDxGGGGGGGxxxxxxxxxxxxxBBBBBBBBBBBBBBBBBBBBBBB
+ */
+static u64
+get_imm64 (u64 insn_addr)
+{
+ u64 *p = (u64 *) (insn_addr & -16); /* mask out slot number */
+
+ return ( (p[1] & 0x0800000000000000UL) << 4) | /*A*/
+ ((p[1] & 0x00000000007fffffUL) << 40) | /*B*/
+ ((p[0] & 0xffffc00000000000UL) >> 24) | /*C*/
+ ((p[1] & 0x0000100000000000UL) >> 23) | /*D*/
+ ((p[1] & 0x0003e00000000000UL) >> 29) | /*E*/
+ ((p[1] & 0x07fc000000000000UL) >> 43) | /*F*/
+ ((p[1] & 0x000007f000000000UL) >> 36); /*G*/
+}
+
+/* Patch instruction with "val" where "mask" has 1 bits. */
+void
+ia64_patch (u64 insn_addr, u64 mask, u64 val)
+{
+ u64 m0, m1, v0, v1, b0, b1, *b = (u64 *) (insn_addr & -16);
+#define insn_mask ((1UL << 41) - 1)
+ unsigned long shift;
+
+ b0 = b[0]; b1 = b[1];
+ /* 5 bits of template, then 3 x 41-bit instructions */
+ shift = 5 + 41 * (insn_addr % 16);
+ if (shift >= 64) {
+ m1 = mask << (shift - 64);
+ v1 = val << (shift - 64);
+ } else {
+ m0 = mask << shift; m1 = mask >> (64 - shift);
+ v0 = val << shift; v1 = val >> (64 - shift);
+ b[0] = (b0 & ~m0) | (v0 & m0);
+ }
+ b[1] = (b1 & ~m1) | (v1 & m1);
+}
+
+void
+ia64_patch_imm64 (u64 insn_addr, u64 val)
+{
+ /* The assembler may generate offset pointing to either slot 1
+ or slot 2 for a long (2-slot) instruction, occupying slots 1
+ and 2. */
+ insn_addr &= -16UL;
+ ia64_patch(insn_addr + 2, 0x01fffefe000UL,
+ (((val & 0x8000000000000000UL) >> 27) | /* bit 63 -> 36 */
+ ((val & 0x0000000000200000UL) << 0) | /* bit 21 -> 21 */
+ ((val & 0x00000000001f0000UL) << 6) | /* bit 16 -> 22 */
+ ((val & 0x000000000000ff80UL) << 20) | /* bit 7 -> 27 */
+ ((val & 0x000000000000007fUL) << 13) /* bit 0 -> 13 */));
+ ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
+}
+
+extern char frametable_miss;
+extern unsigned long xen_pstart;
+
+/*
+ * Add more patch points in seperate functions as appropriate
+ */
+
+static void xen_patch_frametable_miss(u64 offset)
+{
+ u64 addr, val;
+
+ addr = (u64)&frametable_miss;
+ val = get_imm64(addr) + offset;
+ ia64_patch_imm64(addr, val);
+}
+
+
+void xen_patch_kernel(void)
+{
+ unsigned long patch_offset;
+
+ patch_offset = xen_pstart - (KERNEL_START - PAGE_OFFSET);
+
+ printk("Xen patching physical address access by offset: "
+ "0x%lx\n", patch_offset);
+
+ xen_patch_frametable_miss(patch_offset);
+
+ ia64_sync_i();
+ ia64_srlz_i();
+}
diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c
index f3574ca38a..056d3c3cba 100644
--- a/xen/arch/ia64/xen/xensetup.c
+++ b/xen/arch/ia64/xen/xensetup.c
@@ -48,6 +48,7 @@ extern void setup_per_cpu_areas(void);
extern void mem_init(void);
extern void init_IRQ(void);
extern void trap_init(void);
+extern void xen_patch_kernel(void);
/* opt_nosmp: If true, secondary processors are ignored. */
static int opt_nosmp = 0;
@@ -81,6 +82,7 @@ unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
extern long running_on_sim;
unsigned long xen_pstart;
+void *xen_heap_start __read_mostly;
static int
xen_count_pages(u64 start, u64 end, void *arg)
@@ -184,8 +186,8 @@ efi_print(void)
for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
md = p;
- printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
- i, md->type, md->attribute, md->phys_addr,
+ printk("mem%02u: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) "
+ "(%luMB)\n", i, md->type, md->attribute, md->phys_addr,
md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
md->num_pages >> (20 - EFI_PAGE_SHIFT));
}
@@ -242,7 +244,6 @@ md_overlaps(efi_memory_desc_t *md, unsigned long phys_addr)
void start_kernel(void)
{
char *cmdline;
- void *heap_start;
unsigned long nr_pages;
unsigned long dom0_memory_start, dom0_memory_size;
unsigned long dom0_initrd_start, dom0_initrd_size;
@@ -293,6 +294,8 @@ void start_kernel(void)
printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
xen_pstart, xenheap_phys_end);
+ xen_patch_kernel();
+
kern_md = md = efi_get_md(xen_pstart);
md_end = __pa(ia64_imva(&_end));
relo_start = xenheap_phys_end;
@@ -389,10 +392,10 @@ void start_kernel(void)
printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
efi_print();
- heap_start = memguard_init(ia64_imva(&_end));
- printf("Before heap_start: %p\n", heap_start);
- heap_start = __va(init_boot_allocator(__pa(heap_start)));
- printf("After heap_start: %p\n", heap_start);
+ xen_heap_start = memguard_init(ia64_imva(&_end));
+ printf("Before xen_heap_start: %p\n", xen_heap_start);
+ xen_heap_start = __va(init_boot_allocator(__pa(xen_heap_start)));
+ printf("After xen_heap_start: %p\n", xen_heap_start);
efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
efi_memmap_walk(xen_count_pages, &nr_pages);
@@ -410,10 +413,10 @@ void start_kernel(void)
end_boot_allocator();
- init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
+ init_xenheap_pages(__pa(xen_heap_start), xenheap_phys_end);
printk("Xen heap: %luMB (%lukB)\n",
- (xenheap_phys_end-__pa(heap_start)) >> 20,
- (xenheap_phys_end-__pa(heap_start)) >> 10);
+ (xenheap_phys_end-__pa(xen_heap_start)) >> 20,
+ (xenheap_phys_end-__pa(xen_heap_start)) >> 10);
late_setup_arch(&cmdline);
@@ -496,6 +499,8 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
efi.hcdp = NULL;
}
+ expose_p2m_init();
+
/* Create initial domain 0. */
dom0 = domain_create(0);
if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
diff --git a/xen/arch/ia64/xen/xentime.c b/xen/arch/ia64/xen/xentime.c
index 0ebce66c29..c653866969 100644
--- a/xen/arch/ia64/xen/xentime.c
+++ b/xen/arch/ia64/xen/xentime.c
@@ -39,7 +39,7 @@ seqlock_t xtime_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
#define TIME_KEEPER_ID 0
unsigned long domain0_ready = 0;
static s_time_t stime_irq = 0x0; /* System time at last 'time update' */
-unsigned long itc_scale, ns_scale;
+unsigned long itc_scale __read_mostly, ns_scale __read_mostly;
unsigned long itc_at_irq;
/* We don't expect an absolute cycle value here, since then no way
@@ -109,7 +109,6 @@ void
xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long new_itm, old_itc;
- int f_setitm = 0;
#if 0
#define HEARTBEAT_FREQ 16 // period in seconds
@@ -125,20 +124,9 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
#endif
#endif
- if (!is_idle_domain(current->domain)&&!VMX_DOMAIN(current))
- if (vcpu_timer_expired(current)) {
- vcpu_pend_timer(current);
- // ensure another timer interrupt happens even if domain doesn't
- vcpu_set_next_timer(current);
- f_setitm = 1;
- }
new_itm = local_cpu_data->itm_next;
-
- if (f_setitm && !time_after(ia64_get_itc(), new_itm))
- return;
-
- while (1) {
+ while (time_after(ia64_get_itc(), new_itm)) {
new_itm += local_cpu_data->itm_delta;
if (smp_processor_id() == TIME_KEEPER_ID) {
@@ -148,27 +136,32 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
* another CPU. We need to avoid to SMP race by acquiring the
* xtime_lock.
*/
-//#ifdef TURN_ME_OFF_FOR_NOW_IA64_XEN
write_seqlock(&xtime_lock);
-//#endif
#ifdef TURN_ME_OFF_FOR_NOW_IA64_XEN
do_timer(regs);
#endif
- local_cpu_data->itm_next = new_itm;
-
- /* Updates system time (nanoseconds since boot). */
+ /* Updates system time (nanoseconds since boot). */
old_itc = itc_at_irq;
itc_at_irq = ia64_get_itc();
stime_irq += cycle_to_ns(itc_at_irq - old_itc);
-//#ifdef TURN_ME_OFF_FOR_NOW_IA64_XEN
write_sequnlock(&xtime_lock);
-//#endif
- } else
- local_cpu_data->itm_next = new_itm;
+ }
- if (time_after(new_itm, ia64_get_itc()))
- break;
+ local_cpu_data->itm_next = new_itm;
+
+ }
+
+ if (!is_idle_domain(current->domain) && !VMX_DOMAIN(current)) {
+ if (vcpu_timer_expired(current)) {
+ vcpu_pend_timer(current);
+ } else {
+ // ensure another timer interrupt happens
+ // even if domain doesn't
+ vcpu_set_next_timer(current);
+ raise_softirq(TIMER_SOFTIRQ);
+ return;
+ }
}
do {
diff --git a/xen/include/asm-ia64/dom_fw.h b/xen/include/asm-ia64/dom_fw.h
index 841ea9e200..fcf2cb5739 100644
--- a/xen/include/asm-ia64/dom_fw.h
+++ b/xen/include/asm-ia64/dom_fw.h
@@ -39,6 +39,13 @@
#define FW_HYPERCALL_NUM_MASK_HIGH ~0xffUL
#define FW_HYPERCALL_NUM_MASK_LOW 0xffUL
+/* Xen hypercalls are 0-63. */
+#define FW_HYPERCALL_XEN 0x0000UL
+
+/* Define some faster and lighter hypercalls.
+ See definitions in arch-ia64.h */
+#define FW_HYPERCALL_XEN_FAST 0x0200UL
+
/*
* PAL can be called in physical or virtual mode simply by
* branching to pal_entry_point, which is found in one of the
@@ -173,7 +180,7 @@
#define EFI_MEMDESC_VERSION 1
-extern struct ia64_pal_retval xen_pal_emulator(UINT64, u64, u64, u64);
+extern struct ia64_pal_retval xen_pal_emulator(u64, u64, u64, u64);
extern struct sal_ret_values sal_emulator (long index, unsigned long in1, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, unsigned long in7);
extern struct ia64_pal_retval pal_emulator_static (unsigned long);
extern efi_status_t efi_emulator (struct pt_regs *regs, unsigned long *fault);
diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h
index b93351c63c..648eea0636 100644
--- a/xen/include/asm-ia64/domain.h
+++ b/xen/include/asm-ia64/domain.h
@@ -13,28 +13,10 @@
#include <asm/fpswa.h>
#include <xen/rangeset.h>
-struct p2m_entry {
- volatile pte_t* pte;
- pte_t used;
-};
-
-static inline void
-p2m_entry_set(struct p2m_entry* entry, volatile pte_t* pte, pte_t used)
-{
- entry->pte = pte;
- entry->used = used;
-}
-
-static inline int
-p2m_entry_retry(struct p2m_entry* entry)
-{
- //XXX see lookup_domain_pte().
- // NULL is set for invalid gpaddr for the time being.
- if (entry->pte == NULL)
- return 0;
-
- return (pte_val(*entry->pte) != pte_val(entry->used));
-}
+struct p2m_entry;
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+struct tlb_track;
+#endif
extern void domain_relinquish_resources(struct domain *);
struct vcpu;
@@ -67,6 +49,9 @@ struct mm_struct {
struct last_vcpu {
#define INVALID_VCPU_ID INT_MAX
int vcpu_id;
+#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
+ u32 tlbflush_timestamp;
+#endif
} ____cacheline_aligned_in_smp;
/* These are data in domain memory for SAL emulator. */
@@ -87,6 +72,9 @@ struct arch_domain {
unsigned long flags;
struct {
unsigned int is_vti : 1;
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+ unsigned int has_pervcpu_vhpt : 1;
+#endif
};
};
@@ -137,16 +125,21 @@ struct arch_domain {
struct last_vcpu last_vcpu[NR_CPUS];
struct arch_vmx_domain arch_vmx; /* Virtual Machine Extensions */
+
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+ struct tlb_track* tlb_track;
+#endif
};
#define INT_ENABLE_OFFSET(v) \
(sizeof(vcpu_info_t) * (v)->vcpu_id + \
offsetof(vcpu_info_t, evtchn_upcall_mask))
-struct hypercall_param {
- unsigned long va;
- unsigned long pa1;
- unsigned long pa2;
-};
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+#define HAS_PERVCPU_VHPT(d) ((d)->arch.has_pervcpu_vhpt)
+#else
+#define HAS_PERVCPU_VHPT(d) (0)
+#endif
+
struct arch_vcpu {
/* Save the state of vcpu.
@@ -192,8 +185,6 @@ struct arch_vcpu {
char irq_new_condition; // vpsr.i/vtpr change, check for pending VHPI
char hypercall_continuation;
- struct hypercall_param hypercall_param; // used to remap a hypercall param
-
//for phycial emulation
unsigned long old_rsc;
int mode_flags;
@@ -201,6 +192,15 @@ struct arch_vcpu {
struct timer hlt_timer;
struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+ PTA pta;
+ unsigned long vhpt_maddr;
+ struct page_info* vhpt_page;
+ unsigned long vhpt_entries;
+#endif
+#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
+ u32 tlbflush_timestamp;
+#endif
#define INVALID_PROCESSOR INT_MAX
int last_processor;
};
diff --git a/xen/include/asm-ia64/flushtlb.h b/xen/include/asm-ia64/flushtlb.h
new file mode 100644
index 0000000000..0966d72711
--- /dev/null
+++ b/xen/include/asm-ia64/flushtlb.h
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * flushtlb.c
+ * based on x86 flushtlb.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
+ *
+ */
+
+#ifndef __ASM_FLUSHTLB_H__
+#define __ASM_FLUSHTLB_H__
+
+#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
+
+#include <xen/percpu.h>
+
+extern volatile u32 tlbflush_clock;
+#define tlbflush_current_time() tlbflush_clock
+
+u32 tlbflush_clock_inc_and_return(void);
+
+static inline void
+tlbflush_update_time(volatile u32* time, u32 timestamp)
+{
+ /*
+ * this should be ld4.rel + st4.acq. but only have release semantcis.
+ * so this function can't be considered as memory barrier.
+ */
+ *time = timestamp;
+}
+
+/*
+ * taken from x86's NEED_FLUSH()
+ * obj_stamp: mTLB time stamp, per pcpu VHPT stamp, per vcpu VHPT stamp.
+ */
+static inline int
+NEED_FLUSH(u32 obj_stamp, u32 lastuse_stamp)
+{
+ u32 curr_time = tlbflush_current_time();
+ /*
+ * Two cases:
+ * 1. During a wrap, the clock ticks over to 0 while CPUs catch up. For
+ * safety during this period, we force a flush if @curr_time == 0.
+ * 2. Otherwise, we look to see if @cpu_stamp <= @lastuse_stamp.
+ * To detect false positives because @cpu_stamp has wrapped, we
+ * also check @curr_time. If less than @lastuse_stamp we definitely
+ * wrapped, so there's no need for a flush (one is forced every wrap).
+ */
+ return ((curr_time == 0) ||
+ ((obj_stamp <= lastuse_stamp) && (lastuse_stamp <= curr_time)));
+}
+
+DECLARE_PER_CPU(volatile u32, tlbflush_time);
+DECLARE_PER_CPU(volatile u32, vhpt_tlbflush_timestamp);
+
+#else
+
+#define tlbflush_current_time() (0)
+#define tlbflush_clock_inc_and_return() (0)
+#define tlbflush_update_time(time, timestamp) do {(void)timestamp;} while (0)
+#define NEED_FLUSH(obj_stamp, lastuse_stamp) (1)
+
+#endif /* CONFIG_XEN_IA64_TLBFLUSH_CLOCK */
+
+#endif /* __ASM_FLUSHTLB_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-ia64/guest_access.h b/xen/include/asm-ia64/guest_access.h
index 6605578eb9..e0522d4157 100644
--- a/xen/include/asm-ia64/guest_access.h
+++ b/xen/include/asm-ia64/guest_access.h
@@ -1,91 +1,107 @@
-/******************************************************************************
- * guest_access.h
- *
- * Copyright (c) 2006, 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 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.
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ * Tristan Gingold <tristan.gingold@bull.net>
*/
-#ifndef __ASM_IA64_GUEST_ACCESS_H__
-#define __ASM_IA64_GUEST_ACCESS_H__
+#ifndef __ASM_GUEST_ACCESS_H__
+#define __ASM_GUEST_ACCESS_H__
+
+extern unsigned long xencomm_copy_to_guest(void *to, const void *from,
+ unsigned int len, unsigned int skip);
+extern unsigned long xencomm_copy_from_guest(void *to, const void *from,
+ unsigned int len, unsigned int skip);
+extern void *xencomm_add_offset(void *handle, unsigned int bytes);
+extern int xencomm_handle_is_null(void *ptr);
-#include <asm/uaccess.h>
/* Is the guest handle a NULL reference? */
-#define guest_handle_is_null(hnd) ((hnd).p == NULL)
+#define guest_handle_is_null(hnd) \
+ ((hnd).p == NULL || xencomm_handle_is_null((hnd).p))
/* Offset the given guest handle into the array it refers to. */
-#define guest_handle_add_offset(hnd, nr) ((hnd).p += (nr))
+#define guest_handle_add_offset(hnd, nr) ({ \
+ const typeof((hnd).p) _ptr = (hnd).p; \
+ (hnd).p = xencomm_add_offset(_ptr, nr * sizeof(*_ptr)); \
+})
/* Cast a guest handle to the specified type of handle. */
-#define guest_handle_cast(hnd, type) ({ \
- type *_x = (hnd).p; \
- (XEN_GUEST_HANDLE(type)) { _x }; \
+#define guest_handle_cast(hnd, type) ({ \
+ type *_x = (hnd).p; \
+ XEN_GUEST_HANDLE(type) _y; \
+ set_xen_guest_handle(_y, _x); \
+ _y; \
})
-#define guest_handle_from_ptr(ptr, type) ((XEN_GUEST_HANDLE(type)) { (type *)ptr })
-/*
- * Copy an array of objects to guest context via a guest handle,
- * specifying an offset into the guest array.
- */
-#define copy_to_guest_offset(hnd, off, ptr, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
- copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \
-})
+/* Since we run in real mode, we can safely access all addresses. That also
+ * means our __routines are identical to our "normal" routines. */
+#define guest_handle_okay(hnd, nr) 1
/*
- * Copy an array of objects from guest context via a guest handle,
- * specifying an offset into the guest array.
+ * Copy an array of objects to guest context via a guest handle.
+ * Optionally specify an offset into the guest array.
*/
-#define copy_from_guest_offset(ptr, hnd, off, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
- copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \
-})
+#define copy_to_guest_offset(hnd, idx, ptr, nr) \
+ __copy_to_guest_offset(hnd, idx, ptr, nr)
/* Copy sub-field of a structure to guest context via a guest handle. */
-#define copy_field_to_guest(hnd, ptr, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
- copy_to_user(_x, _y, sizeof(*_x)); \
-})
-
-/* Copy sub-field of a structure from guest context via a guest handle. */
-#define copy_field_from_guest(ptr, hnd, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
- copy_from_user(_y, _x, sizeof(*_x)); \
-})
+#define copy_field_to_guest(hnd, ptr, field) \
+ __copy_field_to_guest(hnd, ptr, field)
/*
- * Pre-validate a guest handle.
- * Allows use of faster __copy_* functions.
+ * Copy an array of objects from guest context via a guest handle.
+ * Optionally specify an offset into the guest array.
*/
-#define guest_handle_okay(hnd, nr) \
- array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))
+#define copy_from_guest_offset(ptr, hnd, idx, nr) \
+ __copy_from_guest_offset(ptr, hnd, idx, nr)
-#define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
- __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \
+/* Copy sub-field of a structure from guest context via a guest handle. */
+#define copy_field_from_guest(ptr, hnd, field) \
+ __copy_field_from_guest(ptr, hnd, field)
+
+#define __copy_to_guest_offset(hnd, idx, ptr, nr) ({ \
+ const typeof(ptr) _d = (hnd).p; \
+ const typeof(ptr) _s = (ptr); \
+ xencomm_copy_to_guest(_d, _s, sizeof(*_s)*(nr), sizeof(*_s)*(idx)); \
})
-#define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
- __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \
+#define __copy_field_to_guest(hnd, ptr, field) ({ \
+ const int _off = offsetof(typeof(*ptr), field); \
+ const typeof(ptr) _d = (hnd).p; \
+ const typeof(&(ptr)->field) _s = &(ptr)->field; \
+ xencomm_copy_to_guest(_d, _s, sizeof(*_s), _off); \
})
-#define __copy_field_to_guest(hnd, ptr, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
- __copy_to_user(_x, _y, sizeof(*_x)); \
+#define __copy_from_guest_offset(ptr, hnd, idx, nr) ({ \
+ const typeof(ptr) _s = (hnd).p; \
+ const typeof(ptr) _d = (ptr); \
+ xencomm_copy_from_guest(_d, _s, sizeof(*_s)*(nr), sizeof(*_s)*(idx)); \
})
-#define __copy_field_from_guest(ptr, hnd, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
- __copy_from_user(_y, _x, sizeof(*_x)); \
+#define __copy_field_from_guest(ptr, hnd, field) ({ \
+ const int _off = offsetof(typeof(*ptr), field); \
+ const typeof(ptr) _s = (hnd).p; \
+ const typeof(&(ptr)->field) _d = &(ptr)->field; \
+ xencomm_copy_from_guest(_d, _s, sizeof(*_d), _off); \
})
-#endif /* __ASM_IA64_GUEST_ACCESS_H__ */
+/* Internal use only: returns 0 in case of bad address. */
+extern unsigned long xencomm_paddr_to_maddr(unsigned long paddr);
+
+#endif /* __ASM_GUEST_ACCESS_H__ */
diff --git a/xen/include/asm-ia64/ia64_int.h b/xen/include/asm-ia64/ia64_int.h
index 0bef5b4a1b..711078104b 100644
--- a/xen/include/asm-ia64/ia64_int.h
+++ b/xen/include/asm-ia64/ia64_int.h
@@ -36,7 +36,9 @@
#define IA64_NO_FAULT 0x0000
#define IA64_FAULT 0x0001
#define IA64_RFI_IN_PROGRESS 0x0002
-#define IA64_RETRY 0x0003
+// To avoid conflicting with return value of handle_fpu_swa()
+// set IA64_RETRY to -0x000f
+#define IA64_RETRY (-0x000f)
#define IA64_FORCED_IFA 0x0004
#define IA64_USE_TLB 0x0005
#define IA64_ILLOP_FAULT (IA64_GENEX_VECTOR | 0x00)
diff --git a/xen/include/asm-ia64/linux-xen/asm/cache.h b/xen/include/asm-ia64/linux-xen/asm/cache.h
index 0db88a7044..542d2e23e4 100644
--- a/xen/include/asm-ia64/linux-xen/asm/cache.h
+++ b/xen/include/asm-ia64/linux-xen/asm/cache.h
@@ -32,6 +32,6 @@
#endif
#endif
-#define __read_mostly
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
#endif /* _ASM_IA64_CACHE_H */
diff --git a/xen/include/asm-ia64/linux-xen/asm/pgtable.h b/xen/include/asm-ia64/linux-xen/asm/pgtable.h
index 659c2a933f..7b23205f85 100644
--- a/xen/include/asm-ia64/linux-xen/asm/pgtable.h
+++ b/xen/include/asm-ia64/linux-xen/asm/pgtable.h
@@ -68,6 +68,40 @@
#ifdef XEN
#define _PAGE_VIRT_D (__IA64_UL(1) << 53) /* Virtual dirty bit */
#define _PAGE_PROTNONE 0
+
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+#define _PAGE_TLB_TRACKING_BIT 54
+#define _PAGE_TLB_INSERTED_BIT 55
+#define _PAGE_TLB_INSERTED_MANY_BIT 56
+
+#define _PAGE_TLB_TRACKING (1UL << _PAGE_TLB_TRACKING_BIT)
+#define _PAGE_TLB_INSERTED (1UL << _PAGE_TLB_INSERTED_BIT)
+#define _PAGE_TLB_INSERTED_MANY (1UL << _PAGE_TLB_INSERTED_MANY_BIT)
+#define _PAGE_TLB_TRACK_MASK (_PAGE_TLB_TRACKING | \
+ _PAGE_TLB_INSERTED | \
+ _PAGE_TLB_INSERTED_MANY)
+
+#define pte_tlb_tracking(pte) \
+ ((pte_val(pte) & _PAGE_TLB_TRACKING) != 0)
+#define pte_tlb_inserted(pte) \
+ ((pte_val(pte) & _PAGE_TLB_INSERTED) != 0)
+#define pte_tlb_inserted_many(pte) \
+ ((pte_val(pte) & _PAGE_TLB_INSERTED_MANY) != 0)
+#endif // CONFIG_XEN_IA64_TLB_TRACK
+
+/* domVTI */
+#define GPFN_MEM (0UL << 60) /* Guest pfn is normal mem */
+#define GPFN_FRAME_BUFFER (1UL << 60) /* VGA framebuffer */
+#define GPFN_LOW_MMIO (2UL << 60) /* Low MMIO range */
+#define GPFN_PIB (3UL << 60) /* PIB base */
+#define GPFN_IOSAPIC (4UL << 60) /* IOSAPIC base */
+#define GPFN_LEGACY_IO (5UL << 60) /* Legacy I/O base */
+#define GPFN_GFW (6UL << 60) /* Guest Firmware */
+#define GPFN_HIGH_MMIO (7UL << 60) /* High MMIO range */
+
+#define GPFN_IO_MASK (7UL << 60) /* Guest pfn is I/O type */
+#define GPFN_INV_MASK (1UL << 63) /* Guest pfn is invalid */
+
#else
#define _PAGE_PROTNONE (__IA64_UL(1) << 63)
#endif
diff --git a/xen/include/asm-ia64/linux-xen/asm/processor.h b/xen/include/asm-ia64/linux-xen/asm/processor.h
index 65f65538bc..976c0960d6 100644
--- a/xen/include/asm-ia64/linux-xen/asm/processor.h
+++ b/xen/include/asm-ia64/linux-xen/asm/processor.h
@@ -89,6 +89,7 @@
#ifdef XEN
#include <asm/xenprocessor.h>
+#include <xen/bitops.h>
#else
/* like above but expressed as bitfields for more efficient access: */
struct ia64_psr {
@@ -571,6 +572,23 @@ ia64_eoi (void)
#define cpu_relax() ia64_hint(ia64_hint_pause)
+static inline int
+ia64_get_irr(unsigned int vector)
+{
+ unsigned int reg = vector / 64;
+ unsigned int bit = vector % 64;
+ u64 irr;
+
+ switch (reg) {
+ case 0: irr = ia64_getreg(_IA64_REG_CR_IRR0); break;
+ case 1: irr = ia64_getreg(_IA64_REG_CR_IRR1); break;
+ case 2: irr = ia64_getreg(_IA64_REG_CR_IRR2); break;
+ case 3: irr = ia64_getreg(_IA64_REG_CR_IRR3); break;
+ }
+
+ return test_bit(bit, &irr);
+}
+
static inline void
ia64_set_lrr0 (unsigned long val)
{
diff --git a/xen/include/asm-ia64/linux-xen/asm/system.h b/xen/include/asm-ia64/linux-xen/asm/system.h
index c12beafd3a..9f98e2a743 100644
--- a/xen/include/asm-ia64/linux-xen/asm/system.h
+++ b/xen/include/asm-ia64/linux-xen/asm/system.h
@@ -189,6 +189,7 @@ do { \
#ifdef XEN
#define local_irq_is_enabled() (!irqs_disabled())
+extern struct vcpu *ia64_switch_to(struct vcpu *next_task);
#else
#ifdef __KERNEL__
diff --git a/xen/include/asm-ia64/linux/README.origin b/xen/include/asm-ia64/linux/README.origin
index cb7c02b0a2..e364b52977 100644
--- a/xen/include/asm-ia64/linux/README.origin
+++ b/xen/include/asm-ia64/linux/README.origin
@@ -7,6 +7,7 @@
bcd.h -> linux/include/linux/bcd.h
bitmap.h -> linux/include/linux/bitmap.h
bitops.h -> linux/include/linux/bitops.h
+hash.h -> linux/include/linux/hash.h
initrd.h -> linux/include/linux/initrd.h
jiffies.h -> linux/include/linux/jiffies.h
kmalloc_sizes.h -> linux/include/linux/kmalloc_sizes.h
diff --git a/xen/include/asm-ia64/linux/asm/sal.h b/xen/include/asm-ia64/linux/asm/sal.h
index 29df88bdd2..2af85b14b6 100644
--- a/xen/include/asm-ia64/linux/asm/sal.h
+++ b/xen/include/asm-ia64/linux/asm/sal.h
@@ -657,15 +657,7 @@ ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
return isrv.status;
}
-/* Flush all the processor and platform level instruction and/or data caches */
-static inline s64
-ia64_sal_cache_flush (u64 cache_type)
-{
- struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
- return isrv.status;
-}
-
+extern s64 ia64_sal_cache_flush (u64 cache_type);
/* Initialize all the processor and platform level instruction and data caches */
static inline s64
diff --git a/xen/include/asm-ia64/linux/hash.h b/xen/include/asm-ia64/linux/hash.h
new file mode 100644
index 0000000000..acf17bb8e7
--- /dev/null
+++ b/xen/include/asm-ia64/linux/hash.h
@@ -0,0 +1,58 @@
+#ifndef _LINUX_HASH_H
+#define _LINUX_HASH_H
+/* Fast hashing routine for a long.
+ (C) 2002 William Lee Irwin III, IBM */
+
+/*
+ * Knuth recommends primes in approximately golden ratio to the maximum
+ * integer representable by a machine word for multiplicative hashing.
+ * Chuck Lever verified the effectiveness of this technique:
+ * http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
+ *
+ * These primes are chosen to be bit-sparse, that is operations on
+ * them can use shifts and additions instead of multiplications for
+ * machines where multiplications are slow.
+ */
+#if BITS_PER_LONG == 32
+/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
+#define GOLDEN_RATIO_PRIME 0x9e370001UL
+#elif BITS_PER_LONG == 64
+/* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
+#define GOLDEN_RATIO_PRIME 0x9e37fffffffc0001UL
+#else
+#error Define GOLDEN_RATIO_PRIME for your wordsize.
+#endif
+
+static inline unsigned long hash_long(unsigned long val, unsigned int bits)
+{
+ unsigned long hash = val;
+
+#if BITS_PER_LONG == 64
+ /* Sigh, gcc can't optimise this alone like it does for 32 bits. */
+ unsigned long n = hash;
+ n <<= 18;
+ hash -= n;
+ n <<= 33;
+ hash -= n;
+ n <<= 3;
+ hash += n;
+ n <<= 3;
+ hash -= n;
+ n <<= 4;
+ hash += n;
+ n <<= 2;
+ hash += n;
+#else
+ /* On some cpus multiply is faster, on others gcc will do shifts */
+ hash *= GOLDEN_RATIO_PRIME;
+#endif
+
+ /* High bits are more random, so use them. */
+ return hash >> (BITS_PER_LONG - bits);
+}
+
+static inline unsigned long hash_ptr(void *ptr, unsigned int bits)
+{
+ return hash_long((unsigned long)ptr, bits);
+}
+#endif /* _LINUX_HASH_H */
diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h
index a4f59022bc..ac665bcd0b 100644
--- a/xen/include/asm-ia64/mm.h
+++ b/xen/include/asm-ia64/mm.h
@@ -18,6 +18,7 @@
#include <asm/processor.h>
#include <asm/atomic.h>
#include <asm/tlbflush.h>
+#include <asm/flushtlb.h>
#include <asm/io.h>
#include <public/xen.h>
@@ -117,10 +118,14 @@ struct page_info
#define IS_XEN_HEAP_FRAME(_pfn) ((page_to_maddr(_pfn) < xenheap_phys_end) \
&& (page_to_maddr(_pfn) >= xen_pstart))
-static inline struct domain *unpickle_domptr(u32 _d)
-{ return (_d == 0) ? NULL : __va(_d); }
+extern void *xen_heap_start;
+#define __pickle(a) ((unsigned long)a - (unsigned long)xen_heap_start)
+#define __unpickle(a) (void *)(a + xen_heap_start)
+
+static inline struct domain *unpickle_domptr(u64 _d)
+{ return (_d == 0) ? NULL : __unpickle(_d); }
static inline u32 pickle_domptr(struct domain *_d)
-{ return (_d == NULL) ? 0 : (u32)__pa(_d); }
+{ return (_d == NULL) ? 0 : (u32)__pickle(_d); }
#define page_get_owner(_p) (unpickle_domptr((_p)->u.inuse._domain))
#define page_set_owner(_p, _d) ((_p)->u.inuse._domain = pickle_domptr(_d))
@@ -420,7 +425,7 @@ extern void alloc_dom_xen_and_dom_io(void);
extern void relinquish_mm(struct domain* d);
extern struct page_info * assign_new_domain_page(struct domain *d, unsigned long mpaddr);
extern void assign_new_domain0_page(struct domain *d, unsigned long mpaddr);
-extern void __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags);
+extern int __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags);
extern void assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr);
extern void assign_domain_io_page(struct domain *d, unsigned long mpaddr, unsigned long flags);
struct p2m_entry;
@@ -435,6 +440,13 @@ extern unsigned long ____lookup_domain_mpa(struct domain *d, unsigned long mpadd
extern unsigned long do_dom0vp_op(unsigned long cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3);
extern unsigned long dom0vp_zap_physmap(struct domain *d, unsigned long gpfn, unsigned int extent_order);
extern unsigned long dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn, unsigned long flags, domid_t domid);
+#ifdef CONFIG_XEN_IA64_EXPOSE_P2M
+extern void expose_p2m_init(void);
+extern unsigned long dom0vp_expose_p2m(struct domain* d, unsigned long conv_start_gpfn, unsigned long assign_start_gpfn, unsigned long expose_size, unsigned long granule_pfn);
+#else
+#define expose_p2m_init() do { } while (0)
+#define dom0vp_expose_p2m(d, conv_start_gpfn, assign_start_gpfn, expose_size, granule_pfn) (-ENOSYS)
+#endif
extern volatile unsigned long *mpt_table;
extern unsigned long gmfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
diff --git a/xen/include/asm-ia64/p2m_entry.h b/xen/include/asm-ia64/p2m_entry.h
new file mode 100644
index 0000000000..4a2ff7ef6c
--- /dev/null
+++ b/xen/include/asm-ia64/p2m_entry.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+ * p2m_entry.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
+ *
+ */
+
+#ifndef __ASM_P2M_ENTRY_H__
+#define __ASM_P2M_ENTRY_H__
+
+#include <asm/pgtable.h>
+
+struct p2m_entry {
+#define P2M_PTE_ALWAYS_RETRY ((volatile pte_t*) -1)
+ volatile pte_t* ptep;
+ pte_t used;
+};
+
+static inline void
+p2m_entry_set(struct p2m_entry* entry, volatile pte_t* ptep, pte_t used)
+{
+ entry->ptep = ptep;
+ entry->used = used;
+}
+
+static inline void
+p2m_entry_set_retry(struct p2m_entry* entry)
+{
+ entry->ptep = P2M_PTE_ALWAYS_RETRY;
+}
+
+static inline int
+p2m_entry_retry(struct p2m_entry* entry)
+{
+ /* XXX see lookup_domain_pte().
+ NULL is set for invalid gpaddr for the time being. */
+ if (entry->ptep == NULL)
+ return 0;
+
+ if (entry->ptep == P2M_PTE_ALWAYS_RETRY)
+ return 1;
+
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+ return ((pte_val(*entry->ptep) & ~_PAGE_TLB_TRACK_MASK) !=
+ (pte_val(entry->used) & ~_PAGE_TLB_TRACK_MASK));
+#else
+ return (pte_val(*entry->ptep) != pte_val(entry->used));
+#endif
+}
+
+#endif // __ASM_P2M_ENTRY_H__
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-ia64/perfc_defn.h b/xen/include/asm-ia64/perfc_defn.h
index 58d52a97ff..40c0127c07 100644
--- a/xen/include/asm-ia64/perfc_defn.h
+++ b/xen/include/asm-ia64/perfc_defn.h
@@ -107,3 +107,68 @@ PERFSTATUS(privop_addr_##name##_overflow, "privop-addrs overflow " #name)
PERFPRIVOPADDR(get_ifa)
PERFPRIVOPADDR(thash)
#endif
+
+// vhpt.c
+PERFCOUNTER_CPU(local_vhpt_flush, "local_vhpt_flush")
+PERFCOUNTER_CPU(vcpu_vhpt_flush, "vcpu_vhpt_flush")
+PERFCOUNTER_CPU(vcpu_flush_vtlb_all, "vcpu_flush_vtlb_all")
+PERFCOUNTER_CPU(domain_flush_vtlb_all, "domain_flush_vtlb_all")
+PERFCOUNTER_CPU(vcpu_flush_tlb_vhpt_range, "vcpu_flush_tlb_vhpt_range")
+PERFCOUNTER_CPU(domain_flush_vtlb_track_entry, "domain_flush_vtlb_track_entry")
+PERFCOUNTER_CPU(domain_flush_vtlb_local, "domain_flush_vtlb_local")
+PERFCOUNTER_CPU(domain_flush_vtlb_global, "domain_flush_vtlb_global")
+PERFCOUNTER_CPU(domain_flush_vtlb_range, "domain_flush_vtlb_range")
+
+// domain.c
+PERFCOUNTER_CPU(flush_vtlb_for_context_switch, "flush_vtlb_for_context_switch")
+
+// mm.c
+PERFCOUNTER_CPU(assign_domain_page_replace, "assign_domain_page_replace")
+PERFCOUNTER_CPU(assign_domain_pge_cmpxchg_rel, "assign_domain_pge_cmpxchg_rel")
+PERFCOUNTER_CPU(zap_dcomain_page_one, "zap_dcomain_page_one")
+PERFCOUNTER_CPU(dom0vp_zap_physmap, "dom0vp_zap_physmap")
+PERFCOUNTER_CPU(dom0vp_add_physmap, "dom0vp_add_physmap")
+PERFCOUNTER_CPU(create_grant_host_mapping, "create_grant_host_mapping")
+PERFCOUNTER_CPU(destroy_grant_host_mapping, "destroy_grant_host_mapping")
+PERFCOUNTER_CPU(steal_page_refcount, "steal_page_refcount")
+PERFCOUNTER_CPU(steal_page, "steal_page")
+PERFCOUNTER_CPU(guest_physmap_add_page, "guest_physmap_add_page")
+PERFCOUNTER_CPU(guest_physmap_remove_page, "guest_physmap_remove_page")
+PERFCOUNTER_CPU(domain_page_flush, "domain_page_flush")
+
+// dom0vp
+PERFCOUNTER_CPU(dom0vp_phystomach, "dom0vp_phystomach")
+PERFCOUNTER_CPU(dom0vp_machtophys, "dom0vp_machtophys")
+
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+// insert or dirty
+PERFCOUNTER_CPU(tlb_track_iod, "tlb_track_iod")
+PERFCOUNTER_CPU(tlb_track_iod_again, "tlb_track_iod_again")
+PERFCOUNTER_CPU(tlb_track_iod_not_tracked, "tlb_track_iod_not_tracked")
+PERFCOUNTER_CPU(tlb_track_iod_force_many, "tlb_track_iod_force_many")
+PERFCOUNTER_CPU(tlb_track_iod_tracked_many, "tlb_track_iod_tracked_many")
+PERFCOUNTER_CPU(tlb_track_iod_tracked_many_del, "tlb_track_iod_tracked_many_del")
+PERFCOUNTER_CPU(tlb_track_iod_found, "tlb_track_iod_found")
+PERFCOUNTER_CPU(tlb_track_iod_new_entry, "tlb_track_iod_new_entry")
+PERFCOUNTER_CPU(tlb_track_iod_new_failed, "tlb_track_iod_new_failed")
+PERFCOUNTER_CPU(tlb_track_iod_new_many, "tlb_track_iod_new_many")
+PERFCOUNTER_CPU(tlb_track_iod_insert, "tlb_track_iod_insert")
+PERFCOUNTER_CPU(tlb_track_iod_dirtied, "tlb_track_iod_dirtied")
+
+// search and remove
+PERFCOUNTER_CPU(tlb_track_sar, "tlb_track_sar")
+PERFCOUNTER_CPU(tlb_track_sar_not_tracked, "tlb_track_sar_not_tracked")
+PERFCOUNTER_CPU(tlb_track_sar_not_found, "tlb_track_sar_not_found")
+PERFCOUNTER_CPU(tlb_track_sar_found, "tlb_track_sar_found")
+PERFCOUNTER_CPU(tlb_track_sar_many, "tlb_track_sar_many")
+
+// flush
+PERFCOUNTER_CPU(tlb_track_use_rr7, "tlb_track_use_rr7")
+PERFCOUNTER_CPU(tlb_track_swap_rr0, "tlb_track_swap_rr0")
+#endif
+
+// tlb flush clock
+#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
+PERFCOUNTER_CPU(tlbflush_clock_cswitch_purge, "tlbflush_clock_cswitch_purge")
+PERFCOUNTER_CPU(tlbflush_clock_cswitch_skip, "tlbflush_clock_cswitch_skip")
+#endif
diff --git a/xen/include/asm-ia64/privop.h b/xen/include/asm-ia64/privop.h
index 1324c4c2fb..64e73f473c 100644
--- a/xen/include/asm-ia64/privop.h
+++ b/xen/include/asm-ia64/privop.h
@@ -4,9 +4,9 @@
#include <asm/ia64_int.h>
#include <asm/vcpu.h>
-extern IA64FAULT priv_emulate(VCPU *vcpu, REGS *regs, UINT64 isr);
+extern IA64FAULT priv_emulate(VCPU *vcpu, REGS *regs, u64 isr);
-extern void privify_memory(void *start, UINT64 len);
+extern void privify_memory(void *start, u64 len);
extern int ia64_hyperprivop(unsigned long iim, REGS *regs);
diff --git a/xen/include/asm-ia64/tlb_track.h b/xen/include/asm-ia64/tlb_track.h
new file mode 100644
index 0000000000..5243aa6305
--- /dev/null
+++ b/xen/include/asm-ia64/tlb_track.h
@@ -0,0 +1,155 @@
+/******************************************************************************
+ * tlb_track.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
+ *
+ */
+
+#ifndef __TLB_TRACK_H__
+#define __TLB_TRACK_H__
+
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+
+#include <xen/sched.h>
+#include <xen/perfc.h>
+#include <asm/domain.h>
+#include <xen/list.h>
+#include <asm/p2m_entry.h>
+#include <asm/vcpumask.h>
+
+// TODO: compact this structure.
+struct tlb_track_entry {
+ struct list_head list;
+
+ volatile pte_t* ptep; // corresponding p2m entry
+
+ /* XXX should we use TR_ENTRY? */
+ pte_t pte_val; // mfn and other flags
+ // pte_val.p = 1:
+ // tlb entry is inserted.
+ // pte_val.p = 0:
+ // once tlb entry is inserted, so
+ // this entry is created. But tlb
+ // purge is isseued, so this
+ // virtual address need not to be
+ // purged.
+ unsigned long vaddr; // virtual address
+ unsigned long rid; // rid
+
+ cpumask_t pcpu_dirty_mask;
+ vcpumask_t vcpu_dirty_mask;
+
+#ifdef CONFIG_TLB_TRACK_CNT
+#define TLB_TRACK_CNT_FORCE_MANY 256 /* XXX how many? */
+ unsigned long cnt;
+#endif
+};
+
+struct tlb_track {
+
+/* see __gnttab_map_grant_ref()
+ A domain can map granted-page up to MAPTRACK_MAX_ENTRIES pages. */
+#define TLB_TRACK_LIMIT_ENTRIES \
+ (MAPTRACK_MAX_ENTRIES * (PAGE_SIZE / sizeof(struct tlb_track)))
+
+ spinlock_t free_list_lock;
+ struct list_head free_list;
+ unsigned int limit;
+ unsigned int num_entries;
+ unsigned int num_free;
+ struct list_head page_list;
+
+ /* XXX hash table size */
+ spinlock_t hash_lock;
+ unsigned int hash_size;
+ unsigned int hash_shift;
+ unsigned int hash_mask;
+ struct list_head* hash;
+};
+
+int tlb_track_create(struct domain* d);
+void tlb_track_destroy(struct domain* d);
+
+void tlb_track_free_entry(struct tlb_track* tlb_track,
+ struct tlb_track_entry* entry);
+
+void
+__vcpu_tlb_track_insert_or_dirty(struct vcpu *vcpu, unsigned long vaddr,
+ struct p2m_entry* entry);
+static inline void
+vcpu_tlb_track_insert_or_dirty(struct vcpu *vcpu, unsigned long vaddr,
+ struct p2m_entry* entry)
+{
+ /* optimization.
+ non-tracking pte is most common. */
+ perfc_incrc(tlb_track_iod);
+ if (!pte_tlb_tracking(entry->used)) {
+ perfc_incrc(tlb_track_iod_not_tracked);
+ return;
+ }
+
+ __vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry);
+}
+
+
+/* return value
+ * NULL if this entry is used
+ * entry if this entry isn't used
+ */
+enum TLB_TRACK_RET {
+ TLB_TRACK_NOT_TRACKED,
+ TLB_TRACK_NOT_FOUND,
+ TLB_TRACK_FOUND,
+ TLB_TRACK_MANY,
+ TLB_TRACK_AGAIN,
+};
+typedef enum TLB_TRACK_RET TLB_TRACK_RET_T;
+
+TLB_TRACK_RET_T
+tlb_track_search_and_remove(struct tlb_track* tlb_track,
+ volatile pte_t* ptep, pte_t old_pte,
+ struct tlb_track_entry** entryp);
+
+void
+__tlb_track_entry_printf(const char* func, int line,
+ const struct tlb_track_entry* entry);
+#define tlb_track_entry_printf(entry) \
+ __tlb_track_entry_printf(__func__, __LINE__, (entry))
+#else
+//define as nop
+#define tlb_track_create(d) do { } while (0)
+#define tlb_track_destroy(d) do { } while (0)
+#define tlb_track_free_entry(tlb_track, entry) do { } while (0)
+#define vcpu_tlb_track_insert_or_dirty(vcpu, vaddr, entry) \
+ do { } while (0)
+#define tlb_track_search_and_remove(tlb_track, ptep, old_pte, entryp) \
+ do { } while (0)
+#define tlb_track_entry_printf(entry) do { } while (0)
+#endif /* CONFIG_XEN_IA64_TLB_TRACK */
+
+#endif /* __TLB_TRACK_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-ia64/tlbflush.h b/xen/include/asm-ia64/tlbflush.h
index 22abb53f3f..49ff463b11 100644
--- a/xen/include/asm-ia64/tlbflush.h
+++ b/xen/include/asm-ia64/tlbflush.h
@@ -22,6 +22,15 @@ void domain_flush_vtlb_all (void);
/* Global range-flush of vTLB. */
void domain_flush_vtlb_range (struct domain *d, u64 vadr, u64 addr_range);
+#ifdef CONFIG_XEN_IA64_TLB_TRACK
+struct tlb_track_entry;
+void __domain_flush_vtlb_track_entry(struct domain* d,
+ const struct tlb_track_entry* entry);
+/* Global entry-flush of vTLB */
+void domain_flush_vtlb_track_entry(struct domain* d,
+ const struct tlb_track_entry* entry);
+#endif
+
/* Flush vhpt and mTLB on every dirty cpus. */
void domain_flush_tlb_vhpt(struct domain *d);
@@ -31,7 +40,6 @@ void flush_tlb_mask(cpumask_t mask);
/* Flush local machine TLB. */
void local_flush_tlb_all (void);
-#define tlbflush_current_time() 0
#define tlbflush_filter(x,y) ((void)0)
#endif
diff --git a/xen/include/asm-ia64/uaccess.h b/xen/include/asm-ia64/uaccess.h
index 17e2a17f9d..32ef4151df 100644
--- a/xen/include/asm-ia64/uaccess.h
+++ b/xen/include/asm-ia64/uaccess.h
@@ -211,30 +211,16 @@ extern void __put_user_unknown (void);
extern unsigned long __must_check __copy_user (void __user *to, const void __user *from,
unsigned long count);
-extern int ia64_map_hypercall_param(void);
-
static inline unsigned long
__copy_to_user (void __user *to, const void *from, unsigned long count)
{
- unsigned long len;
- len = __copy_user(to, (void __user *)from, count);
- if (len == 0)
- return 0;
- if (ia64_map_hypercall_param())
- len = __copy_user(to, (void __user *)from, count); /* retry */
- return len;
+ return __copy_user(to, (void __user *)from, count);
}
static inline unsigned long
__copy_from_user (void *to, const void __user *from, unsigned long count)
{
- unsigned long len;
- len = __copy_user((void __user *)to, from, count);
- if (len == 0)
- return 0;
- if (ia64_map_hypercall_param())
- len = __copy_user((void __user *) to, from, count); /* retry */
- return len;
+ return __copy_user((void __user *)to, from, count);
}
#define __copy_to_user_inatomic __copy_to_user
diff --git a/xen/include/asm-ia64/vcpu.h b/xen/include/asm-ia64/vcpu.h
index 7bfc76f761..3a6af9d2d6 100644
--- a/xen/include/asm-ia64/vcpu.h
+++ b/xen/include/asm-ia64/vcpu.h
@@ -10,194 +10,194 @@
#include <asm/ia64_int.h>
#include <xen/types.h>
#include <public/xen.h>
-typedef unsigned long UINT64;
-typedef unsigned int UINT;
-typedef int BOOLEAN;
+typedef int BOOLEAN;
struct vcpu;
-typedef struct vcpu VCPU;
+typedef struct vcpu VCPU;
typedef cpu_user_regs_t REGS;
extern u64 cycle_to_ns(u64 cycle);
/* Note: PSCB stands for Privilegied State Communication Block. */
#define VCPU(_v,_x) (_v->arch.privregs->_x)
-#define PSCB(_v,_x) VCPU(_v,_x)
-#define PSCBX(_v,_x) (_v->arch._x)
+#define PSCB(_v,_x) VCPU(_v,_x)
+#define PSCBX(_v,_x) (_v->arch._x)
#define SPURIOUS_VECTOR 0xf
/* general registers */
-extern UINT64 vcpu_get_gr(VCPU *vcpu, unsigned long reg);
-extern IA64FAULT vcpu_get_gr_nat(VCPU *vcpu, unsigned long reg, UINT64 *val);
-extern IA64FAULT vcpu_set_gr(VCPU *vcpu, unsigned long reg, UINT64 value, int nat);
-extern IA64FAULT vcpu_get_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val);
+extern u64 vcpu_get_gr(VCPU * vcpu, unsigned long reg);
+extern IA64FAULT vcpu_get_gr_nat(VCPU * vcpu, unsigned long reg, u64 * val);
+extern IA64FAULT vcpu_set_gr(VCPU * vcpu, unsigned long reg, u64 value,
+ int nat);
+extern IA64FAULT vcpu_get_fpreg(VCPU * vcpu, unsigned long reg,
+ struct ia64_fpreg *val);
-extern IA64FAULT vcpu_set_fpreg(VCPU *vcpu, unsigned long reg, struct ia64_fpreg *val);
+extern IA64FAULT vcpu_set_fpreg(VCPU * vcpu, unsigned long reg,
+ struct ia64_fpreg *val);
/* application registers */
-extern void vcpu_load_kernel_regs(VCPU *vcpu);
-extern IA64FAULT vcpu_set_ar(VCPU *vcpu, UINT64 reg, UINT64 val);
-extern IA64FAULT vcpu_get_ar(VCPU *vcpu, UINT64 reg, UINT64 *val);
+extern void vcpu_load_kernel_regs(VCPU * vcpu);
+extern IA64FAULT vcpu_set_ar(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vcpu_get_ar(VCPU * vcpu, u64 reg, u64 * val);
/* psr */
-extern BOOLEAN vcpu_get_psr_ic(VCPU *vcpu);
-extern UINT64 vcpu_get_ipsr_int_state(VCPU *vcpu,UINT64 prevpsr);
-extern IA64FAULT vcpu_get_psr(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm);
-extern IA64FAULT vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm);
-extern IA64FAULT vcpu_set_psr_l(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_psr_i(VCPU *vcpu);
-extern IA64FAULT vcpu_reset_psr_dt(VCPU *vcpu);
-extern IA64FAULT vcpu_set_psr_dt(VCPU *vcpu);
+extern BOOLEAN vcpu_get_psr_ic(VCPU * vcpu);
+extern u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr);
+extern IA64FAULT vcpu_get_psr(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm);
+extern IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm);
+extern IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_psr_i(VCPU * vcpu);
+extern IA64FAULT vcpu_reset_psr_dt(VCPU * vcpu);
+extern IA64FAULT vcpu_set_psr_dt(VCPU * vcpu);
/* control registers */
-extern IA64FAULT vcpu_set_dcr(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_itm(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_iva(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_pta(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_ipsr(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_isr(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_iip(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_ifa(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_itir(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_iipa(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_ifs(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_iim(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_iha(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_lid(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_tpr(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_eoi(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_lrr0(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_lrr1(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_get_dcr(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_itm(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_iva(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_pta(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_ipsr(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_isr(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_increment_iip(VCPU *vcpu);
-extern IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_itir(VCPU *vcpu, UINT64 *pval);
-extern unsigned long vcpu_get_itir_on_fault(VCPU *vcpu, UINT64 ifa);
-extern IA64FAULT vcpu_get_iipa(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_ifs(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_iim(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_lid(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_tpr(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_irr0(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_irr1(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_irr2(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_irr3(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_lrr0(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_get_lrr1(VCPU *vcpu, UINT64 *pval);
+extern IA64FAULT vcpu_set_dcr(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_iva(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_pta(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_ipsr(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_isr(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_iip(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_ifa(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_itir(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_iipa(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_ifs(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_iim(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_iha(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_get_dcr(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_iva(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_pta(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_ipsr(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_isr(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_iip(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_increment_iip(VCPU * vcpu);
+extern IA64FAULT vcpu_get_ifa(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_itir(VCPU * vcpu, u64 * pval);
+extern unsigned long vcpu_get_itir_on_fault(VCPU * vcpu, u64 ifa);
+extern IA64FAULT vcpu_get_iipa(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_ifs(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_iim(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_iha(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_lid(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval);
/* interrupt registers */
-extern void vcpu_pend_unspecified_interrupt(VCPU *vcpu);
-extern UINT64 vcpu_check_pending_interrupts(VCPU *vcpu);
-extern IA64FAULT vcpu_get_itv(VCPU *vcpu,UINT64 *pval);
-extern IA64FAULT vcpu_get_pmv(VCPU *vcpu,UINT64 *pval);
-extern IA64FAULT vcpu_get_cmcv(VCPU *vcpu,UINT64 *pval);
-extern IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval);
-extern IA64FAULT vcpu_set_itv(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_pmv(VCPU *vcpu, UINT64 val);
-extern IA64FAULT vcpu_set_cmcv(VCPU *vcpu, UINT64 val);
+extern void vcpu_pend_unspecified_interrupt(VCPU * vcpu);
+extern u64 vcpu_check_pending_interrupts(VCPU * vcpu);
+extern IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_get_ivr(VCPU * vcpu, u64 * pval);
+extern IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val);
+extern IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val);
/* interval timer registers */
-extern IA64FAULT vcpu_set_itc(VCPU *vcpu,UINT64 val);
-extern UINT64 vcpu_timer_pending_early(VCPU *vcpu);
+extern IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val);
+extern u64 vcpu_timer_pending_early(VCPU * vcpu);
/* debug breakpoint registers */
-extern IA64FAULT vcpu_set_ibr(VCPU *vcpu,UINT64 reg,UINT64 val);
-extern IA64FAULT vcpu_set_dbr(VCPU *vcpu,UINT64 reg,UINT64 val);
-extern IA64FAULT vcpu_get_ibr(VCPU *vcpu,UINT64 reg,UINT64 *pval);
-extern IA64FAULT vcpu_get_dbr(VCPU *vcpu,UINT64 reg,UINT64 *pval);
+extern IA64FAULT vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval);
+extern IA64FAULT vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval);
/* performance monitor registers */
-extern IA64FAULT vcpu_set_pmc(VCPU *vcpu,UINT64 reg,UINT64 val);
-extern IA64FAULT vcpu_set_pmd(VCPU *vcpu,UINT64 reg,UINT64 val);
-extern IA64FAULT vcpu_get_pmc(VCPU *vcpu,UINT64 reg,UINT64 *pval);
-extern IA64FAULT vcpu_get_pmd(VCPU *vcpu,UINT64 reg,UINT64 *pval);
+extern IA64FAULT vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval);
+extern IA64FAULT vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval);
/* banked general registers */
-extern IA64FAULT vcpu_bsw0(VCPU *vcpu);
-extern IA64FAULT vcpu_bsw1(VCPU *vcpu);
+extern IA64FAULT vcpu_bsw0(VCPU * vcpu);
+extern IA64FAULT vcpu_bsw1(VCPU * vcpu);
/* region registers */
-extern IA64FAULT vcpu_set_rr(VCPU *vcpu,UINT64 reg,UINT64 val);
-extern IA64FAULT vcpu_get_rr(VCPU *vcpu,UINT64 reg,UINT64 *pval);
-extern IA64FAULT vcpu_get_rr_ve(VCPU *vcpu,UINT64 vadr);
+extern IA64FAULT vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vcpu_get_rr(VCPU * vcpu, u64 reg, u64 * pval);
+extern IA64FAULT vcpu_get_rr_ve(VCPU * vcpu, u64 vadr);
/* protection key registers */
-extern IA64FAULT vcpu_get_pkr(VCPU *vcpu, UINT64 reg, UINT64 *pval);
-extern IA64FAULT vcpu_set_pkr(VCPU *vcpu, UINT64 reg, UINT64 val);
-extern IA64FAULT vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key);
+extern IA64FAULT vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval);
+extern IA64FAULT vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key);
/* TLB */
-static inline void vcpu_purge_tr_entry(TR_ENTRY *trp)
+static inline void vcpu_purge_tr_entry(TR_ENTRY * trp)
{
trp->pte.val = 0;
}
-extern IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 padr,
- UINT64 itir, UINT64 ifa);
-extern IA64FAULT vcpu_itr_i(VCPU *vcpu, UINT64 slot, UINT64 padr,
- UINT64 itir, UINT64 ifa);
-extern IA64FAULT vcpu_itc_d(VCPU *vcpu, UINT64 padr, UINT64 itir, UINT64 ifa);
-extern IA64FAULT vcpu_itc_i(VCPU *vcpu, UINT64 padr, UINT64 itir, UINT64 ifa);
-extern IA64FAULT vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 log_range);
-extern IA64FAULT vcpu_ptc_e(VCPU *vcpu, UINT64 vadr);
-extern IA64FAULT vcpu_ptc_g(VCPU *vcpu, UINT64 vadr, UINT64 addr_range);
-extern IA64FAULT vcpu_ptc_ga(VCPU *vcpu, UINT64 vadr, UINT64 addr_range);
-extern IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr, UINT64 log_range);
-extern IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr, UINT64 log_range);
+extern IA64FAULT vcpu_itr_d(VCPU * vcpu, u64 slot, u64 padr, u64 itir, u64 ifa);
+extern IA64FAULT vcpu_itr_i(VCPU * vcpu, u64 slot, u64 padr, u64 itir, u64 ifa);
+extern IA64FAULT vcpu_itc_d(VCPU * vcpu, u64 padr, u64 itir, u64 ifa);
+extern IA64FAULT vcpu_itc_i(VCPU * vcpu, u64 padr, u64 itir, u64 ifa);
+extern IA64FAULT vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 log_range);
+extern IA64FAULT vcpu_ptc_e(VCPU * vcpu, u64 vadr);
+extern IA64FAULT vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 addr_range);
+extern IA64FAULT vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 addr_range);
+extern IA64FAULT vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 log_range);
+extern IA64FAULT vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 log_range);
union U_IA64_BUNDLE;
-extern int vcpu_get_domain_bundle(VCPU *vcpu, REGS *regs, UINT64 gip, union U_IA64_BUNDLE *bundle);
-extern IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data,
- UINT64 *pteval, UINT64 *itir, UINT64 *iha);
-extern IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr);
-extern IA64FAULT vcpu_force_inst_miss(VCPU *vcpu, UINT64 ifa);
-extern IA64FAULT vcpu_force_data_miss(VCPU *vcpu, UINT64 ifa);
-extern IA64FAULT vcpu_fc(VCPU *vcpu, UINT64 vadr);
+extern int vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
+ union U_IA64_BUNDLE *bundle);
+extern IA64FAULT vcpu_translate(VCPU * vcpu, u64 address, BOOLEAN is_data,
+ u64 * pteval, u64 * itir, u64 * iha);
+extern IA64FAULT vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr);
+extern IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa);
+extern IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa);
+extern IA64FAULT vcpu_fc(VCPU * vcpu, u64 vadr);
/* misc */
-extern IA64FAULT vcpu_rfi(VCPU *vcpu);
-extern IA64FAULT vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval);
-extern IA64FAULT vcpu_cover(VCPU *vcpu);
-extern IA64FAULT vcpu_ttag(VCPU *vcpu, UINT64 vadr, UINT64 *padr);
-extern IA64FAULT vcpu_get_cpuid(VCPU *vcpu, UINT64 reg, UINT64 *pval);
-
-extern void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector);
-extern void vcpu_pend_timer(VCPU *vcpu);
-extern void vcpu_poke_timer(VCPU *vcpu);
-extern void vcpu_set_next_timer(VCPU *vcpu);
-extern BOOLEAN vcpu_timer_expired(VCPU *vcpu);
-extern UINT64 vcpu_deliverable_interrupts(VCPU *vcpu);
-extern void vcpu_itc_no_srlz(VCPU *vcpu, UINT64, UINT64, UINT64, UINT64, UINT64);
-extern UINT64 vcpu_get_tmp(VCPU *, UINT64);
-extern void vcpu_set_tmp(VCPU *, UINT64, UINT64);
-
-extern IA64FAULT vcpu_set_dtr(VCPU *vcpu, u64 slot,
+extern IA64FAULT vcpu_rfi(VCPU * vcpu);
+extern IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval);
+extern IA64FAULT vcpu_cover(VCPU * vcpu);
+extern IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr);
+extern IA64FAULT vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval);
+
+extern void vcpu_pend_interrupt(VCPU * vcpu, u64 vector);
+extern void vcpu_pend_timer(VCPU * vcpu);
+extern void vcpu_poke_timer(VCPU * vcpu);
+extern void vcpu_set_next_timer(VCPU * vcpu);
+extern BOOLEAN vcpu_timer_expired(VCPU * vcpu);
+extern u64 vcpu_deliverable_interrupts(VCPU * vcpu);
+struct p2m_entry;
+extern void vcpu_itc_no_srlz(VCPU * vcpu, u64, u64, u64, u64, u64,
+ struct p2m_entry *);
+extern u64 vcpu_get_tmp(VCPU *, u64);
+extern void vcpu_set_tmp(VCPU *, u64, u64);
+
+extern IA64FAULT vcpu_set_dtr(VCPU * vcpu, u64 slot,
u64 pte, u64 itir, u64 ifa, u64 rid);
-extern IA64FAULT vcpu_set_itr(VCPU *vcpu, u64 slot,
+extern IA64FAULT vcpu_set_itr(VCPU * vcpu, u64 slot,
u64 pte, u64 itir, u64 ifa, u64 rid);
/* Initialize vcpu regs. */
-extern void vcpu_init_regs (struct vcpu *v);
+extern void vcpu_init_regs(struct vcpu *v);
-static inline UINT64
-itir_ps(UINT64 itir)
+static inline u64 itir_ps(u64 itir)
{
- return ((itir >> 2) & 0x3f);
+ return ((itir >> 2) & 0x3f);
}
-static inline UINT64
-itir_mask(UINT64 itir)
+static inline u64 itir_mask(u64 itir)
{
- return (~((1UL << itir_ps(itir)) - 1));
+ return (~((1UL << itir_ps(itir)) - 1));
}
-static inline s64
-vcpu_get_next_timer_ns(VCPU *vcpu)
+static inline s64 vcpu_get_next_timer_ns(VCPU * vcpu)
{
- s64 vcpu_get_next_timer_ns;
- u64 d = PSCBX(vcpu, domain_itm);
- u64 now = ia64_get_itc();
+ s64 vcpu_get_next_timer_ns;
+ u64 d = PSCBX(vcpu, domain_itm);
+ u64 now = ia64_get_itc();
- if (d > now)
- vcpu_get_next_timer_ns = cycle_to_ns(d - now) + NOW();
- else
- vcpu_get_next_timer_ns = cycle_to_ns(local_cpu_data->itm_delta) + NOW();
+ if (d > now)
+ vcpu_get_next_timer_ns = cycle_to_ns(d - now) + NOW();
+ else
+ vcpu_get_next_timer_ns =
+ cycle_to_ns(local_cpu_data->itm_delta) + NOW();
- return vcpu_get_next_timer_ns;
+ return vcpu_get_next_timer_ns;
}
#define verbose(a...) do {if (vcpu_verbose) printf(a);} while(0)
@@ -208,5 +208,4 @@ vcpu_get_next_timer_ns(VCPU *vcpu)
#define vcpu_quick_region_set(_tr_regions,_ifa) \
do {_tr_regions |= (1 << ((unsigned long)_ifa >> 61)); } while (0)
-
#endif
diff --git a/xen/include/asm-ia64/vcpumask.h b/xen/include/asm-ia64/vcpumask.h
new file mode 100644
index 0000000000..7a9773e411
--- /dev/null
+++ b/xen/include/asm-ia64/vcpumask.h
@@ -0,0 +1,60 @@
+#ifndef __XEN_VCPUMASK_H
+#define __XEN_VCPUMASK_H
+
+/* vcpu mask
+ stolen from cpumask.h */
+typedef struct { DECLARE_BITMAP(bits, MAX_VIRT_CPUS); } vcpumask_t;
+
+#define vcpu_set(vcpu, dst) __vcpu_set((vcpu), &(dst))
+static inline void __vcpu_set(int vcpu, volatile vcpumask_t *dstp)
+{
+ set_bit(vcpu, dstp->bits);
+}
+#define vcpus_clear(dst) __vcpus_clear(&(dst), MAX_VIRT_CPUS)
+static inline void __vcpus_clear(vcpumask_t *dstp, int nbits)
+{
+ bitmap_zero(dstp->bits, nbits);
+}
+/* No static inline type checking - see Subtlety (1) above. */
+#define vcpu_isset(vcpu, vcpumask) test_bit((vcpu), (vcpumask).bits)
+
+#define first_vcpu(src) __first_vcpu(&(src), MAX_VIRT_CPUS)
+static inline int __first_vcpu(const vcpumask_t *srcp, int nbits)
+{
+ return min_t(int, nbits, find_first_bit(srcp->bits, nbits));
+}
+
+#define next_vcpu(n, src) __next_vcpu((n), &(src), MAX_VIRT_CPUS)
+static inline int __next_vcpu(int n, const vcpumask_t *srcp, int nbits)
+{
+ return min_t(int, nbits, find_next_bit(srcp->bits, nbits, n+1));
+}
+
+#if MAX_VIRT_CPUS > 1
+#define for_each_vcpu_mask(vcpu, mask) \
+ for ((vcpu) = first_vcpu(mask); \
+ (vcpu) < MAX_VIRT_CPUS; \
+ (vcpu) = next_vcpu((vcpu), (mask)))
+#else /* NR_CPUS == 1 */
+#define for_each_vcpu_mask(vcpu, mask) for ((vcpu) = 0; (vcpu) < 1; (vcpu)++)
+#endif /* NR_CPUS */
+
+#define vcpumask_scnprintf(buf, len, src) \
+ __vcpumask_scnprintf((buf), (len), &(src), MAX_VIRT_CPUS)
+static inline int __vcpumask_scnprintf(char *buf, int len,
+ const vcpumask_t *srcp, int nbits)
+{
+ return bitmap_scnprintf(buf, len, srcp->bits, nbits);
+}
+
+#endif /* __XEN_VCPUMASK_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-ia64/vhpt.h b/xen/include/asm-ia64/vhpt.h
index cb4fc30462..351c1d701a 100644
--- a/xen/include/asm-ia64/vhpt.h
+++ b/xen/include/asm-ia64/vhpt.h
@@ -18,6 +18,10 @@
#ifndef __ASSEMBLY__
#include <xen/percpu.h>
+#include <asm/vcpumask.h>
+
+extern void domain_purge_swtc_entries(struct domain *d);
+extern void domain_purge_swtc_entries_vcpu_dirty_mask(struct domain* d, vcpumask_t vcpu_dirty_mask);
//
// VHPT Long Format Entry (as recognized by hw)
@@ -37,11 +41,48 @@ extern void vhpt_multiple_insert(unsigned long vaddr, unsigned long pte,
unsigned long logps);
extern void vhpt_insert (unsigned long vadr, unsigned long pte,
unsigned long logps);
-void vhpt_flush(void);
+void local_vhpt_flush(void);
+extern void vcpu_vhpt_flush(struct vcpu* v);
/* Currently the VHPT is allocated per CPU. */
DECLARE_PER_CPU (unsigned long, vhpt_paddr);
DECLARE_PER_CPU (unsigned long, vhpt_pend);
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+#if !VHPT_ENABLED
+#error "VHPT_ENABLED must be set for CONFIG_XEN_IA64_PERVCPU_VHPT"
+#endif
+#endif
+
+#include <xen/sched.h>
+int pervcpu_vhpt_alloc(struct vcpu *v);
+void pervcpu_vhpt_free(struct vcpu *v);
+static inline unsigned long
+vcpu_vhpt_maddr(struct vcpu* v)
+{
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+ if (HAS_PERVCPU_VHPT(v->domain))
+ return v->arch.vhpt_maddr;
+#endif
+
+#if 0
+ // referencecing v->processor is racy.
+ return per_cpu(vhpt_paddr, v->processor);
+#endif
+ BUG_ON(v != current);
+ return __get_cpu_var(vhpt_paddr);
+}
+
+static inline unsigned long
+vcpu_pta(struct vcpu* v)
+{
+#ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
+ if (HAS_PERVCPU_VHPT(v->domain))
+ return v->arch.pta.val;
+#endif
+ return __va_ul(__get_cpu_var(vhpt_paddr)) | (1 << 8) |
+ (VHPT_SIZE_LOG2 << 2) | VHPT_ENABLED;
+}
+
#endif /* !__ASSEMBLY */
#endif
diff --git a/xen/include/asm-ia64/vmx.h b/xen/include/asm-ia64/vmx.h
index b9d9a67779..577fc1e34d 100644
--- a/xen/include/asm-ia64/vmx.h
+++ b/xen/include/asm-ia64/vmx.h
@@ -35,6 +35,7 @@ extern void vmx_final_setup_guest(struct vcpu *v);
extern void vmx_save_state(struct vcpu *v);
extern void vmx_load_state(struct vcpu *v);
extern void vmx_setup_platform(struct domain *d);
+extern void vmx_do_launch(struct vcpu *v);
extern void vmx_io_assist(struct vcpu *v);
extern int ia64_hypercall (struct pt_regs *regs);
extern void vmx_save_state(struct vcpu *v);
diff --git a/xen/include/asm-ia64/vmx_pal_vsa.h b/xen/include/asm-ia64/vmx_pal_vsa.h
index 72ad1e6ca7..7ce8069501 100644
--- a/xen/include/asm-ia64/vmx_pal_vsa.h
+++ b/xen/include/asm-ia64/vmx_pal_vsa.h
@@ -26,10 +26,9 @@
/* PAL virtualization services */
#ifndef __ASSEMBLY__
-extern UINT64 ia64_call_vsa(UINT64 proc,UINT64 arg1, UINT64 arg2,
- UINT64 arg3, UINT64 arg4, UINT64 arg5,
- UINT64 arg6, UINT64 arg7);
-extern UINT64 __vsa_base;
+extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5, u64 arg6, u64 arg7);
+extern u64 __vsa_base;
#endif /* __ASSEMBLY__ */
#define PAL_VPS_RESUME_NORMAL 0x0000
diff --git a/xen/include/asm-ia64/vmx_phy_mode.h b/xen/include/asm-ia64/vmx_phy_mode.h
index 02f8cc643f..bf9afde404 100644
--- a/xen/include/asm-ia64/vmx_phy_mode.h
+++ b/xen/include/asm-ia64/vmx_phy_mode.h
@@ -90,7 +90,7 @@ extern void physical_mode_init(VCPU *);
extern void switch_to_physical_rid(VCPU *);
extern void switch_to_virtual_rid(VCPU *vcpu);
extern void switch_mm_mode(VCPU *vcpu, IA64_PSR old_psr, IA64_PSR new_psr);
-extern void stlb_phys_lookup(VCPU *vcpu, UINT64 paddr, UINT64 type);
+extern void stlb_phys_lookup(VCPU *vcpu, u64 paddr, u64 type);
extern void check_mm_mode_switch (VCPU *vcpu, IA64_PSR old_psr, IA64_PSR new_psr);
extern void prepare_if_physical_mode(VCPU *vcpu);
extern void recover_if_physical_mode(VCPU *vcpu);
@@ -120,9 +120,4 @@ extern void physical_tlb_miss(VCPU *vcpu, u64 vadr);
#define GUEST_VIRT 1 /* Guest in virtual mode */
#define GUEST_PHYS 2 /* Guest in physical mode, requiring emulation */
-
-
#endif /* _PHY_MODE_H_ */
-
-
-
diff --git a/xen/include/asm-ia64/vmx_uaccess.h b/xen/include/asm-ia64/vmx_uaccess.h
deleted file mode 100644
index a6e27425f6..0000000000
--- a/xen/include/asm-ia64/vmx_uaccess.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
-/*
- * vmx_uaccess.h: Defines vmx specific macros to transfer memory areas
- * across the domain/hypervisor boundary.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Note: For vmx enabled environment, poor man's policy is actually
- * useless since HV resides in completely different address space as
- * domain. So the only way to do the access is search vTLB first, and
- * access identity mapped address if hit.
- *
- * Copyright (c) 2004, Intel Corporation.
- * Kun Tian (Kevin Tian) (kevin.tian@intel.com)
- */
-
-#ifndef __ASM_IA64_VMX_UACCESS_H__
-#define __ASM_IA64_VMX_UACCESS_H__
-
-#include <xen/compiler.h>
-#include <xen/errno.h>
-#include <xen/sched.h>
-
-#include <asm/intrinsics.h>
-#include <asm/vmmu.h>
-
-/* Since HV never accesses domain space directly, most security check can
- * be dummy now
- */
-asm (".section \"__ex_table\", \"a\"\n\t.previous");
-
-/* For back compatibility */
-#define __access_ok(addr, size, segment) 1
-#define access_ok(addr, size, segment) __access_ok((addr), (size), (segment))
-
-/*
- * These are the main single-value transfer routines. They automatically
- * use the right size if we just have the right pointer type.
- *
- * Careful to not
- * (a) re-use the arguments for side effects (sizeof/typeof is ok)
- * (b) require any knowledge of processes at this stage
- */
-#define put_user(x, ptr) __put_user((x), (ptr))
-#define get_user(x, ptr) __get_user((x), (ptr))
-
-#define __put_user(x, ptr) __do_put_user((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
-#define __get_user(x, ptr) __do_get_user((x), (ptr), sizeof(*(ptr)))
-
-/* TODO: add specific unaligned access later. If assuming aligned at
- * 1,2,4,8 bytes by far, it's impossible for operand spaning two
- * vTLB entry
- */
-extern long
-__domain_va_to_ma(unsigned long va, unsigned long* ma, unsigned long *len);
-
-#define __do_put_user(x, ptr, size) \
-({ \
- __typeof__ (x) __pu_x = (x); \
- __typeof__ (*(ptr)) __user *__pu_ptr = (ptr); \
- __typeof__ (size) __pu_size = (size); \
- unsigned long __pu_ma; \
- long __pu_err; \
- \
- __pu_err = __domain_va_to_ma((unsigned long)__pu_ptr, \
- &__pu_ma, &__pu_size); \
- __pu_err ? (__pu_err = -EFAULT) : \
- (*((__typeof__ (*(ptr)) *)__va(__pu_ma)) = x); \
- __pu_err; \
-})
-
-#define __do_get_user(x, ptr, size) \
-({ \
- __typeof__ (x) __gu_x = (x); \
- __typeof__ (*(ptr)) __user *__gu_ptr = (ptr); \
- __typeof__ (size) __gu_size = (size); \
- unsigned long __gu_ma; \
- long __gu_err; \
- \
- __gu_err = __domain_va_to_ma((unsigned long)__gu_ptr, \
- &__gu_ma, &__gu_size); \
- __gu_err ? (__gu_err = -EFAULT) : \
- (x = *((__typeof__ (*(ptr)) *)__va(__gu_ma))); \
- __gu_err; \
-})
-
-/* More complex copy from domain */
-#define copy_from_user(to, from, n) __copy_from_user((to), (from), (n))
-#define copy_to_user(to, from, n) __copy_to_user((to), (from), (n))
-#define clear_user(to, n) __clear_user((t0), (n))
-
-static inline unsigned long
-__copy_from_user(void *to, void *from, unsigned long n)
-{
- unsigned long ma, i;
-
- i = n;
- while(!__domain_va_to_ma((unsigned long)from, &ma, &i)) {
- memcpy(to, (void *)__va(ma), i);
- n -= i;
- if (!n)
- break;
- from += i;
- to += i;
- i = n;
- }
- return n;
-}
-
-static inline unsigned long
-__copy_to_user(void *to, void *from, unsigned long n)
-{
- unsigned long ma, i;
-
- i = n;
- while(!__domain_va_to_ma((unsigned long)to, &ma, &i)) {
- memcpy((void *)__va(ma), from, i);
- n -= i;
- if (!n)
- break;
- from += i;
- to += i;
- i = n;
- }
- return n;
-}
-
-static inline unsigned long
-__clear_user(void *to, unsigned long n)
-{
- unsigned long ma, i;
-
- i = n;
- while(!__domain_va_to_ma((unsigned long)to, &ma, &i)) {
- memset((void *)__va(ma), 0, i);
- n -= i;
- if (!n)
- break;
- to += i;
- i = n;
- }
- return n;
-}
-
-#endif // __ASM_IA64_VMX_UACCESS_H__
diff --git a/xen/include/asm-ia64/vmx_vcpu.h b/xen/include/asm-ia64/vmx_vcpu.h
index a82e31fb7f..0defc0d4f4 100644
--- a/xen/include/asm-ia64/vmx_vcpu.h
+++ b/xen/include/asm-ia64/vmx_vcpu.h
@@ -1,4 +1,4 @@
-/* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
+/* -*- Mode:C; c-basic-offset:8; tab-width:8; indent-tabs-mode:nil -*- */
/*
* vmx_vcpu.h:
* Copyright (c) 2005, Intel Corporation.
@@ -23,7 +23,6 @@
#ifndef _XEN_IA64_VMX_VCPU_H
#define _XEN_IA64_VMX_VCPU_H
-
#include <xen/sched.h>
#include <asm/ia64_int.h>
#include <asm/vmx_vpd.h>
@@ -33,462 +32,438 @@
#include <asm/types.h>
#include <asm/vcpu.h>
-#define VRN_SHIFT 61
-#define VRN0 0x0UL
-#define VRN1 0x1UL
-#define VRN2 0x2UL
-#define VRN3 0x3UL
-#define VRN4 0x4UL
-#define VRN5 0x5UL
-#define VRN6 0x6UL
-#define VRN7 0x7UL
+#define VRN_SHIFT 61
+#define VRN0 0x0UL
+#define VRN1 0x1UL
+#define VRN2 0x2UL
+#define VRN3 0x3UL
+#define VRN4 0x4UL
+#define VRN5 0x5UL
+#define VRN6 0x6UL
+#define VRN7 0x7UL
// for vlsapic
-#define VLSAPIC_INSVC(vcpu, i) ((vcpu)->arch.insvc[i])
+#define VLSAPIC_INSVC(vcpu, i) ((vcpu)->arch.insvc[i])
#define VMX(x,y) ((x)->arch.arch_vmx.y)
+#define VMM_RR_SHIFT 20
+#define VMM_RR_MASK ((1UL<<VMM_RR_SHIFT)-1)
-#define VMM_RR_SHIFT 20
-#define VMM_RR_MASK ((1UL<<VMM_RR_SHIFT)-1)
-
-extern u64 indirect_reg_igfld_MASK ( int type, int index, u64 value);
-extern u64 cr_igfld_mask (int index, u64 value);
-extern int check_indirect_reg_rsv_fields ( int type, int index, u64 value );
-extern u64 set_isr_ei_ni (VCPU *vcpu);
-extern u64 set_isr_for_na_inst(VCPU *vcpu, int op);
-
+extern u64 indirect_reg_igfld_MASK(int type, int index, u64 value);
+extern u64 cr_igfld_mask(int index, u64 value);
+extern int check_indirect_reg_rsv_fields(int type, int index, u64 value);
+extern u64 set_isr_ei_ni(VCPU * vcpu);
+extern u64 set_isr_for_na_inst(VCPU * vcpu, int op);
/* next all for VTI domain APIs definition */
-extern void vmx_vcpu_set_psr(VCPU *vcpu, unsigned long value);
-extern UINT64 vmx_vcpu_sync_mpsr(UINT64 mipsr, UINT64 value);
-extern void vmx_vcpu_set_psr_sync_mpsr(VCPU * vcpu, UINT64 value);
-extern IA64FAULT vmx_vcpu_cover(VCPU *vcpu);
-extern IA64FAULT vmx_vcpu_set_rr(VCPU *vcpu, UINT64 reg, UINT64 val);
-extern IA64FAULT vmx_vcpu_get_pkr(VCPU *vcpu, UINT64 reg, UINT64 *pval);
-IA64FAULT vmx_vcpu_set_pkr(VCPU *vcpu, UINT64 reg, UINT64 val);
-extern IA64FAULT vmx_vcpu_itc_i(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa);
-extern IA64FAULT vmx_vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa);
-extern IA64FAULT vmx_vcpu_itr_i(VCPU *vcpu, UINT64 slot, UINT64 pte, UINT64 itir, UINT64 ifa);
-extern IA64FAULT vmx_vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte, UINT64 itir, UINT64 ifa);
-extern IA64FAULT vmx_vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 ps);
-extern IA64FAULT vmx_vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 ps);
-extern IA64FAULT vmx_vcpu_ptc_l(VCPU *vcpu, UINT64 vadr, UINT64 ps);
-extern IA64FAULT vmx_vcpu_ptc_e(VCPU *vcpu, UINT64 vadr);
-extern IA64FAULT vmx_vcpu_ptc_g(VCPU *vcpu, UINT64 vadr, UINT64 ps);
-extern IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu,UINT64 vadr,UINT64 ps);
-extern IA64FAULT vmx_vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval);
-extern u64 vmx_vcpu_get_itir_on_fault(VCPU *vcpu, u64 ifa);
-extern IA64FAULT vmx_vcpu_ttag(VCPU *vcpu, UINT64 vadr, UINT64 *pval);
-extern IA64FAULT vmx_vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr);
-extern IA64FAULT vmx_vcpu_tak(VCPU *vcpu, UINT64 vadr, UINT64 *key);
-extern IA64FAULT vmx_vcpu_rfi(VCPU *vcpu);
-extern UINT64 vmx_vcpu_get_psr(VCPU *vcpu);
-extern IA64FAULT vmx_vcpu_get_bgr(VCPU *vcpu, unsigned int reg, UINT64 *val);
-extern IA64FAULT vmx_vcpu_set_bgr(VCPU *vcpu, unsigned int reg, u64 val,int nat);
+extern void vmx_vcpu_set_psr(VCPU * vcpu, unsigned long value);
+extern u64 vmx_vcpu_sync_mpsr(u64 mipsr, u64 value);
+extern void vmx_vcpu_set_psr_sync_mpsr(VCPU * vcpu, u64 value);
+extern IA64FAULT vmx_vcpu_cover(VCPU * vcpu);
+extern IA64FAULT vmx_vcpu_set_rr(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vmx_vcpu_get_pkr(VCPU * vcpu, u64 reg, u64 * pval);
+IA64FAULT vmx_vcpu_set_pkr(VCPU * vcpu, u64 reg, u64 val);
+extern IA64FAULT vmx_vcpu_itc_i(VCPU * vcpu, u64 pte, u64 itir, u64 ifa);
+extern IA64FAULT vmx_vcpu_itc_d(VCPU * vcpu, u64 pte, u64 itir, u64 ifa);
+extern IA64FAULT vmx_vcpu_itr_i(VCPU * vcpu, u64 slot, u64 pte, u64 itir,
+ u64 ifa);
+extern IA64FAULT vmx_vcpu_itr_d(VCPU * vcpu, u64 slot, u64 pte, u64 itir,
+ u64 ifa);
+extern IA64FAULT vmx_vcpu_ptr_d(VCPU * vcpu, u64 vadr, u64 ps);
+extern IA64FAULT vmx_vcpu_ptr_i(VCPU * vcpu, u64 vadr, u64 ps);
+extern IA64FAULT vmx_vcpu_ptc_l(VCPU * vcpu, u64 vadr, u64 ps);
+extern IA64FAULT vmx_vcpu_ptc_e(VCPU * vcpu, u64 vadr);
+extern IA64FAULT vmx_vcpu_ptc_g(VCPU * vcpu, u64 vadr, u64 ps);
+extern IA64FAULT vmx_vcpu_ptc_ga(VCPU * vcpu, u64 vadr, u64 ps);
+extern IA64FAULT vmx_vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval);
+extern u64 vmx_vcpu_get_itir_on_fault(VCPU * vcpu, u64 ifa);
+extern IA64FAULT vmx_vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * pval);
+extern IA64FAULT vmx_vcpu_tpa(VCPU * vcpu, u64 vadr, u64 * padr);
+extern IA64FAULT vmx_vcpu_tak(VCPU * vcpu, u64 vadr, u64 * key);
+extern IA64FAULT vmx_vcpu_rfi(VCPU * vcpu);
+extern u64 vmx_vcpu_get_psr(VCPU * vcpu);
+extern IA64FAULT vmx_vcpu_get_bgr(VCPU * vcpu, unsigned int reg, u64 * val);
+extern IA64FAULT vmx_vcpu_set_bgr(VCPU * vcpu, unsigned int reg, u64 val,
+ int nat);
#if 0
-extern IA64FAULT vmx_vcpu_get_gr(VCPU *vcpu, unsigned reg, UINT64 * val);
-extern IA64FAULT vmx_vcpu_set_gr(VCPU *vcpu, unsigned reg, u64 value, int nat);
+extern IA64FAULT vmx_vcpu_get_gr(VCPU * vcpu, unsigned reg, u64 * val);
+extern IA64FAULT vmx_vcpu_set_gr(VCPU * vcpu, unsigned reg, u64 value, int nat);
#endif
-extern IA64FAULT vmx_vcpu_reset_psr_sm(VCPU *vcpu, UINT64 imm24);
-extern IA64FAULT vmx_vcpu_set_psr_sm(VCPU *vcpu, UINT64 imm24);
-extern IA64FAULT vmx_vcpu_set_psr_l(VCPU *vcpu, UINT64 val);
-extern void vtm_init(VCPU *vcpu);
-extern uint64_t vtm_get_itc(VCPU *vcpu);
-extern void vtm_set_itc(VCPU *vcpu, uint64_t new_itc);
-extern void vtm_set_itv(VCPU *vcpu, uint64_t val);
-extern void vtm_set_itm(VCPU *vcpu, uint64_t val);
-extern void vtm_interruption_update(VCPU *vcpu, vtime_t* vtm);
+extern IA64FAULT vmx_vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24);
+extern IA64FAULT vmx_vcpu_set_psr_sm(VCPU * vcpu, u64 imm24);
+extern IA64FAULT vmx_vcpu_set_psr_l(VCPU * vcpu, u64 val);
+extern void vtm_init(VCPU * vcpu);
+extern uint64_t vtm_get_itc(VCPU * vcpu);
+extern void vtm_set_itc(VCPU * vcpu, uint64_t new_itc);
+extern void vtm_set_itv(VCPU * vcpu, uint64_t val);
+extern void vtm_set_itm(VCPU * vcpu, uint64_t val);
+extern void vtm_interruption_update(VCPU * vcpu, vtime_t * vtm);
//extern void vtm_domain_out(VCPU *vcpu);
//extern void vtm_domain_in(VCPU *vcpu);
-extern void vlsapic_reset(VCPU *vcpu);
-extern int vmx_check_pending_irq(VCPU *vcpu);
-extern void guest_write_eoi(VCPU *vcpu);
-extern int is_unmasked_irq(VCPU *vcpu);
-extern uint64_t guest_read_vivr(VCPU *vcpu);
-extern void vmx_inject_vhpi(VCPU *vcpu, u8 vec);
-extern int vmx_vcpu_pend_interrupt(VCPU *vcpu, uint8_t vector);
-extern struct virtual_platform_def *vmx_vcpu_get_plat(VCPU *vcpu);
-extern void memread_p(VCPU *vcpu, u64 *src, u64 *dest, size_t s);
-extern void memread_v(VCPU *vcpu, thash_data_t *vtlb, u64 *src, u64 *dest, size_t s);
-extern void memwrite_v(VCPU *vcpu, thash_data_t *vtlb, u64 *src, u64 *dest, size_t s);
-extern void memwrite_p(VCPU *vcpu, u64 *src, u64 *dest, size_t s);
-extern void vcpu_load_kernel_regs(VCPU *vcpu);
-extern IA64FAULT vmx_vcpu_increment_iip(VCPU *vcpu);
-extern void vmx_switch_rr7(unsigned long ,shared_info_t*,void *,void *,void *);
-
-extern void dtlb_fault (VCPU *vcpu, u64 vadr);
-extern void nested_dtlb (VCPU *vcpu);
-extern void alt_dtlb (VCPU *vcpu, u64 vadr);
-extern void dvhpt_fault (VCPU *vcpu, u64 vadr);
-extern void dnat_page_consumption (VCPU *vcpu, uint64_t vadr);
-extern void page_not_present(VCPU *vcpu, u64 vadr);
-extern void data_access_rights(VCPU *vcpu, u64 vadr);
+extern void vlsapic_reset(VCPU * vcpu);
+extern int vmx_check_pending_irq(VCPU * vcpu);
+extern void guest_write_eoi(VCPU * vcpu);
+extern int is_unmasked_irq(VCPU * vcpu);
+extern uint64_t guest_read_vivr(VCPU * vcpu);
+extern void vmx_inject_vhpi(VCPU * vcpu, u8 vec);
+extern int vmx_vcpu_pend_interrupt(VCPU * vcpu, uint8_t vector);
+extern struct virtual_platform_def *vmx_vcpu_get_plat(VCPU * vcpu);
+extern void memread_p(VCPU * vcpu, u64 * src, u64 * dest, size_t s);
+extern void memread_v(VCPU * vcpu, thash_data_t * vtlb, u64 * src, u64 * dest,
+ size_t s);
+extern void memwrite_v(VCPU * vcpu, thash_data_t * vtlb, u64 * src, u64 * dest,
+ size_t s);
+extern void memwrite_p(VCPU * vcpu, u64 * src, u64 * dest, size_t s);
+extern void vcpu_load_kernel_regs(VCPU * vcpu);
+extern IA64FAULT vmx_vcpu_increment_iip(VCPU * vcpu);
+extern IA64FAULT vmx_vcpu_decrement_iip(VCPU * vcpu);
+extern void vmx_switch_rr7(unsigned long, shared_info_t *, void *, void *,
+ void *);
+
+extern void dtlb_fault(VCPU * vcpu, u64 vadr);
+extern void nested_dtlb(VCPU * vcpu);
+extern void alt_dtlb(VCPU * vcpu, u64 vadr);
+extern void dvhpt_fault(VCPU * vcpu, u64 vadr);
+extern void dnat_page_consumption(VCPU * vcpu, uint64_t vadr);
+extern void data_page_not_present(VCPU * vcpu, u64 vadr);
+extern void inst_page_not_present(VCPU * vcpu, u64 vadr);
+extern void data_access_rights(VCPU * vcpu, u64 vadr);
/**************************************************************************
VCPU control register access routines
**************************************************************************/
-static inline
-IA64FAULT vmx_vcpu_get_dcr(VCPU *vcpu, UINT64 *pval)
+static inline IA64FAULT vmx_vcpu_get_dcr(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,dcr);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, dcr);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_itm(VCPU *vcpu, UINT64 *pval)
+static inline IA64FAULT vmx_vcpu_get_itm(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,itm);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, itm);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_iva(VCPU *vcpu, UINT64 *pval)
+static inline IA64FAULT vmx_vcpu_get_iva(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,iva);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, iva);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_pta(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_pta(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,pta);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, pta);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_lid(VCPU *vcpu, UINT64 *pval)
+static inline IA64FAULT vmx_vcpu_get_lid(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,lid);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, lid);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_ivr(VCPU * vcpu, u64 * pval)
{
- *pval = guest_read_vivr(vcpu);
- return (IA64_NO_FAULT);
+ *pval = guest_read_vivr(vcpu);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_tpr(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_tpr(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,tpr);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, tpr);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_eoi(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_eoi(VCPU * vcpu, u64 * pval)
{
- *pval = 0L; // reads of eoi always return 0
- return (IA64_NO_FAULT);
+ *pval = 0L; // reads of eoi always return 0
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_irr0(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_irr0(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,irr[0]);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, irr[0]);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_irr1(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_irr1(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,irr[1]);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, irr[1]);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_irr2(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_irr2(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,irr[2]);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, irr[2]);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_irr3(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_irr3(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,irr[3]);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, irr[3]);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_itv(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_itv(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,itv);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, itv);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_pmv(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_pmv(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,pmv);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, pmv);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_cmcv(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_cmcv(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,cmcv);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, cmcv);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_lrr0(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_lrr0(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,lrr0);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, lrr0);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_lrr1(VCPU *vcpu, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_lrr1(VCPU * vcpu, u64 * pval)
{
- *pval = VCPU(vcpu,lrr1);
- return (IA64_NO_FAULT);
+ *pval = VCPU(vcpu, lrr1);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_dcr(VCPU *vcpu, u64 val)
-{
- u64 mdcr, mask;
- VCPU(vcpu,dcr)=val;
- /* All vDCR bits will go to mDCR, except for be/pp/dm bits */
- mdcr = ia64_get_dcr();
- /* Machine dcr.dm masked to handle guest ld.s on tr mapped page */
- mask = IA64_DCR_BE | IA64_DCR_PP | IA64_DCR_DM;
- mdcr = ( mdcr & mask ) | ( val & (~mask) );
- ia64_set_dcr( mdcr);
- VMX(vcpu, mdcr) = mdcr;
- return IA64_NO_FAULT;
+
+static inline IA64FAULT vmx_vcpu_set_dcr(VCPU * vcpu, u64 val)
+{
+ u64 mdcr, mask;
+ VCPU(vcpu, dcr) = val;
+ /* All vDCR bits will go to mDCR, except for be/pp/dm bits */
+ mdcr = ia64_get_dcr();
+ /* Machine dcr.dm masked to handle guest ld.s on tr mapped page */
+ mask = IA64_DCR_BE | IA64_DCR_PP | IA64_DCR_DM;
+ mdcr = (mdcr & mask) | (val & (~mask));
+ ia64_set_dcr(mdcr);
+ VMX(vcpu, mdcr) = mdcr;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_itm(VCPU *vcpu, u64 val)
+static inline IA64FAULT vmx_vcpu_set_itm(VCPU * vcpu, u64 val)
{
- vtm_set_itm(vcpu, val);
- return IA64_NO_FAULT;
+ vtm_set_itm(vcpu, val);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_iva(VCPU *vcpu, u64 val)
+
+static inline IA64FAULT vmx_vcpu_set_iva(VCPU * vcpu, u64 val)
{
- VCPU(vcpu,iva)=val;
- return IA64_NO_FAULT;
+ VCPU(vcpu, iva) = val;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_pta(VCPU *vcpu, u64 val)
+static inline IA64FAULT vmx_vcpu_set_pta(VCPU * vcpu, u64 val)
{
- VCPU(vcpu,pta)=val;
- return IA64_NO_FAULT;
+ VCPU(vcpu, pta) = val;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_lid(VCPU *vcpu, u64 val)
+static inline IA64FAULT vmx_vcpu_set_lid(VCPU * vcpu, u64 val)
{
- VCPU(vcpu,lid)=val;
- return IA64_NO_FAULT;
+ VCPU(vcpu, lid) = val;
+ return IA64_NO_FAULT;
}
-extern IA64FAULT vmx_vcpu_set_tpr(VCPU *vcpu, u64 val);
+extern IA64FAULT vmx_vcpu_set_tpr(VCPU * vcpu, u64 val);
-static inline
-IA64FAULT
-vmx_vcpu_set_eoi(VCPU *vcpu, u64 val)
+static inline IA64FAULT vmx_vcpu_set_eoi(VCPU * vcpu, u64 val)
{
- guest_write_eoi(vcpu);
- return IA64_NO_FAULT;
+ guest_write_eoi(vcpu);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_itv(VCPU *vcpu, u64 val)
+static inline IA64FAULT vmx_vcpu_set_itv(VCPU * vcpu, u64 val)
{
- vtm_set_itv(vcpu, val);
- return IA64_NO_FAULT;
+ vtm_set_itv(vcpu, val);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_pmv(VCPU *vcpu, u64 val)
+
+static inline IA64FAULT vmx_vcpu_set_pmv(VCPU * vcpu, u64 val)
{
- VCPU(vcpu,pmv)=val;
- return IA64_NO_FAULT;
+ VCPU(vcpu, pmv) = val;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_cmcv(VCPU *vcpu, u64 val)
+
+static inline IA64FAULT vmx_vcpu_set_cmcv(VCPU * vcpu, u64 val)
{
- VCPU(vcpu,cmcv)=val;
- return IA64_NO_FAULT;
+ VCPU(vcpu, cmcv) = val;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_lrr0(VCPU *vcpu, u64 val)
+
+static inline IA64FAULT vmx_vcpu_set_lrr0(VCPU * vcpu, u64 val)
{
- VCPU(vcpu,lrr0)=val;
- return IA64_NO_FAULT;
+ VCPU(vcpu, lrr0) = val;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT
-vmx_vcpu_set_lrr1(VCPU *vcpu, u64 val)
+
+static inline IA64FAULT vmx_vcpu_set_lrr1(VCPU * vcpu, u64 val)
{
- VCPU(vcpu,lrr1)=val;
- return IA64_NO_FAULT;
+ VCPU(vcpu, lrr1) = val;
+ return IA64_NO_FAULT;
}
-
-
-
/**************************************************************************
VCPU privileged application register access routines
**************************************************************************/
-static inline
-IA64FAULT vmx_vcpu_set_itc(VCPU *vcpu, UINT64 val)
+static inline IA64FAULT vmx_vcpu_set_itc(VCPU * vcpu, u64 val)
{
- vtm_set_itc(vcpu, val);
- return IA64_NO_FAULT;
+ vtm_set_itc(vcpu, val);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_itc(VCPU *vcpu,UINT64 *val)
+
+static inline IA64FAULT vmx_vcpu_get_itc(VCPU * vcpu, u64 * val)
{
- *val = vtm_get_itc(vcpu);
- return IA64_NO_FAULT;
+ *val = vtm_get_itc(vcpu);
+ return IA64_NO_FAULT;
}
+
/*
static inline
-IA64FAULT vmx_vcpu_get_rr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+IA64FAULT vmx_vcpu_get_rr(VCPU *vcpu, u64 reg, u64 *pval)
{
*pval = VMX(vcpu,vrr[reg>>61]);
- return (IA64_NO_FAULT);
+ return IA64_NO_FAULT;
}
*/
/**************************************************************************
VCPU debug breakpoint register access routines
**************************************************************************/
-static inline
-IA64FAULT vmx_vcpu_get_cpuid(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+static inline IA64FAULT vmx_vcpu_get_cpuid(VCPU * vcpu, u64 reg, u64 * pval)
{
- // TODO: unimplemented DBRs return a reserved register fault
- // TODO: Should set Logical CPU state, not just physical
- if(reg > 4){
- panic_domain(vcpu_regs(vcpu),"there are only five cpuid registers");
- }
- *pval=VCPU(vcpu,vcpuid[reg]);
- return (IA64_NO_FAULT);
+ // TODO: unimplemented DBRs return a reserved register fault
+ // TODO: Should set Logical CPU state, not just physical
+ if (reg > 4) {
+ panic_domain(vcpu_regs(vcpu),
+ "there are only five cpuid registers");
+ }
+ *pval = VCPU(vcpu, vcpuid[reg]);
+ return IA64_NO_FAULT;
}
-
-static inline
-IA64FAULT vmx_vcpu_set_dbr(VCPU *vcpu, UINT64 reg, UINT64 val)
+static inline IA64FAULT vmx_vcpu_set_dbr(VCPU * vcpu, u64 reg, u64 val)
{
- // TODO: unimplemented DBRs return a reserved register fault
- // TODO: Should set Logical CPU state, not just physical
- ia64_set_dbr(reg,val);
- return (IA64_NO_FAULT);
+ // TODO: unimplemented DBRs return a reserved register fault
+ // TODO: Should set Logical CPU state, not just physical
+ ia64_set_dbr(reg, val);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_set_ibr(VCPU *vcpu, UINT64 reg, UINT64 val)
+
+static inline IA64FAULT vmx_vcpu_set_ibr(VCPU * vcpu, u64 reg, u64 val)
{
- // TODO: unimplemented IBRs return a reserved register fault
- // TODO: Should set Logical CPU state, not just physical
- ia64_set_ibr(reg,val);
- return (IA64_NO_FAULT);
+ // TODO: unimplemented IBRs return a reserved register fault
+ // TODO: Should set Logical CPU state, not just physical
+ ia64_set_ibr(reg, val);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_dbr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_dbr(VCPU * vcpu, u64 reg, u64 * pval)
{
- // TODO: unimplemented DBRs return a reserved register fault
- UINT64 val = ia64_get_dbr(reg);
- *pval = val;
- return (IA64_NO_FAULT);
+ // TODO: unimplemented DBRs return a reserved register fault
+ u64 val = ia64_get_dbr(reg);
+ *pval = val;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_ibr(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_ibr(VCPU * vcpu, u64 reg, u64 * pval)
{
- // TODO: unimplemented IBRs return a reserved register fault
- UINT64 val = ia64_get_ibr(reg);
- *pval = val;
- return (IA64_NO_FAULT);
+ // TODO: unimplemented IBRs return a reserved register fault
+ u64 val = ia64_get_ibr(reg);
+ *pval = val;
+ return IA64_NO_FAULT;
}
/**************************************************************************
VCPU performance monitor register access routines
**************************************************************************/
-static inline
-IA64FAULT vmx_vcpu_set_pmc(VCPU *vcpu, UINT64 reg, UINT64 val)
+static inline IA64FAULT vmx_vcpu_set_pmc(VCPU * vcpu, u64 reg, u64 val)
{
- // TODO: Should set Logical CPU state, not just physical
- // NOTE: Writes to unimplemented PMC registers are discarded
- ia64_set_pmc(reg,val);
- return (IA64_NO_FAULT);
+ // TODO: Should set Logical CPU state, not just physical
+ // NOTE: Writes to unimplemented PMC registers are discarded
+ ia64_set_pmc(reg, val);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_set_pmd(VCPU *vcpu, UINT64 reg, UINT64 val)
+
+static inline IA64FAULT vmx_vcpu_set_pmd(VCPU * vcpu, u64 reg, u64 val)
{
- // TODO: Should set Logical CPU state, not just physical
- // NOTE: Writes to unimplemented PMD registers are discarded
- ia64_set_pmd(reg,val);
- return (IA64_NO_FAULT);
+ // TODO: Should set Logical CPU state, not just physical
+ // NOTE: Writes to unimplemented PMD registers are discarded
+ ia64_set_pmd(reg, val);
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_pmc(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_pmc(VCPU * vcpu, u64 reg, u64 * pval)
{
- // NOTE: Reads from unimplemented PMC registers return zero
- UINT64 val = (UINT64)ia64_get_pmc(reg);
- *pval = val;
- return (IA64_NO_FAULT);
+ // NOTE: Reads from unimplemented PMC registers return zero
+ u64 val = (u64) ia64_get_pmc(reg);
+ *pval = val;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_get_pmd(VCPU *vcpu, UINT64 reg, UINT64 *pval)
+
+static inline IA64FAULT vmx_vcpu_get_pmd(VCPU * vcpu, u64 reg, u64 * pval)
{
- // NOTE: Reads from unimplemented PMD registers return zero
- UINT64 val = (UINT64)ia64_get_pmd(reg);
- *pval = val;
- return (IA64_NO_FAULT);
+ // NOTE: Reads from unimplemented PMD registers return zero
+ u64 val = (u64) ia64_get_pmd(reg);
+ *pval = val;
+ return IA64_NO_FAULT;
}
/**************************************************************************
VCPU banked general register access routines
**************************************************************************/
#if 0
-static inline
-IA64FAULT vmx_vcpu_bsw0(VCPU *vcpu)
+static inline IA64FAULT vmx_vcpu_bsw0(VCPU * vcpu)
{
- VCPU(vcpu,vpsr) &= ~IA64_PSR_BN;
- return (IA64_NO_FAULT);
+ VCPU(vcpu, vpsr) &= ~IA64_PSR_BN;
+ return IA64_NO_FAULT;
}
-static inline
-IA64FAULT vmx_vcpu_bsw1(VCPU *vcpu)
+
+static inline IA64FAULT vmx_vcpu_bsw1(VCPU * vcpu)
{
- VCPU(vcpu,vpsr) |= IA64_PSR_BN;
- return (IA64_NO_FAULT);
+ VCPU(vcpu, vpsr) |= IA64_PSR_BN;
+ return IA64_NO_FAULT;
}
#endif
#if 0
/* Another hash performance algorithm */
#define redistribute_rid(rid) (((rid) & ~0xffff) | (((rid) << 8) & 0xff00) | (((rid) >> 8) & 0xff))
#endif
-static inline unsigned long
-vrrtomrr(VCPU *v, unsigned long val)
+static inline unsigned long vrrtomrr(VCPU * v, unsigned long val)
{
- ia64_rr rr;
+ ia64_rr rr;
- rr.rrval=val;
- rr.rid = rr.rid + v->arch.starting_rid;
- if (rr.ps > PAGE_SHIFT)
- rr.ps = PAGE_SHIFT;
- rr.ve = 1;
- return vmMangleRID(rr.rrval);
+ rr.rrval = val;
+ rr.rid = rr.rid + v->arch.starting_rid;
+ if (rr.ps > PAGE_SHIFT)
+ rr.ps = PAGE_SHIFT;
+ rr.ve = 1;
+ return vmMangleRID(rr.rrval);
/* Disable this rid allocation algorithm for now */
#if 0
- rid=(((u64)vcpu->domain->domain_id)<<DOMAIN_RID_SHIFT) + rr.rid;
- rr.rid = redistribute_rid(rid);
-#endif
+ rid = (((u64) vcpu->domain->domain_id) << DOMAIN_RID_SHIFT) + rr.rid;
+ rr.rid = redistribute_rid(rid);
+#endif
}
-static inline thash_cb_t *
-vmx_vcpu_get_vtlb(VCPU *vcpu)
+static inline thash_cb_t *vmx_vcpu_get_vtlb(VCPU * vcpu)
{
- return &vcpu->arch.vtlb;
+ return &vcpu->arch.vtlb;
}
-static inline thash_cb_t *
-vcpu_get_vhpt(VCPU *vcpu)
+static inline thash_cb_t *vcpu_get_vhpt(VCPU * vcpu)
{
- return &vcpu->arch.vhpt;
+ return &vcpu->arch.vhpt;
}
#endif
diff --git a/xen/include/asm-ia64/xenkregs.h b/xen/include/asm-ia64/xenkregs.h
index dcfaf65d6b..d2dcd2bc84 100644
--- a/xen/include/asm-ia64/xenkregs.h
+++ b/xen/include/asm-ia64/xenkregs.h
@@ -7,8 +7,7 @@
#define IA64_TR_SHARED_INFO 3 /* dtr3: page shared with domain */
#define IA64_TR_VHPT 4 /* dtr4: vhpt */
#define IA64_TR_MAPPED_REGS 5 /* dtr5: vcpu mapped regs */
-#define IA64_TR_PERVP_VHPT 6
-#define IA64_DTR_GUEST_KERNEL 7
+#define IA64_DTR_GUEST_KERNEL 6
#define IA64_ITR_GUEST_KERNEL 2
/* Processor status register bits: */
#define IA64_PSR_VM_BIT 46
diff --git a/xen/include/asm-ia64/xensystem.h b/xen/include/asm-ia64/xensystem.h
index d7c40e1735..d966d1917b 100644
--- a/xen/include/asm-ia64/xensystem.h
+++ b/xen/include/asm-ia64/xensystem.h
@@ -22,7 +22,6 @@
#define GATE_ADDR KERNEL_START
#define DEFAULT_SHAREDINFO_ADDR 0xf100000000000000
#define PERCPU_ADDR (DEFAULT_SHAREDINFO_ADDR - PERCPU_PAGE_SIZE)
-#define VHPT_ADDR 0xf200000000000000
#ifdef CONFIG_VIRTUAL_FRAME_TABLE
#define VIRT_FRAME_TABLE_ADDR 0xf300000000000000
#define VIRT_FRAME_TABLE_END 0xf400000000000000
diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h
index 98bda1d241..fd05ff9233 100644
--- a/xen/include/public/arch-ia64.h
+++ b/xen/include/public/arch-ia64.h
@@ -48,18 +48,6 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
typedef unsigned long xen_ulong_t;
-#define GPFN_MEM (0UL << 56) /* Guest pfn is normal mem */
-#define GPFN_FRAME_BUFFER (1UL << 56) /* VGA framebuffer */
-#define GPFN_LOW_MMIO (2UL << 56) /* Low MMIO range */
-#define GPFN_PIB (3UL << 56) /* PIB base */
-#define GPFN_IOSAPIC (4UL << 56) /* IOSAPIC base */
-#define GPFN_LEGACY_IO (5UL << 56) /* Legacy I/O base */
-#define GPFN_GFW (6UL << 56) /* Guest Firmware */
-#define GPFN_HIGH_MMIO (7UL << 56) /* High MMIO range */
-
-#define GPFN_IO_MASK (7UL << 56) /* Guest pfn is I/O type */
-#define GPFN_INV_MASK (31UL << 59) /* Guest pfn is invalid */
-
#define INVALID_MFN (~0UL)
#define MEM_G (1UL << 30)
@@ -336,33 +324,33 @@ struct vcpu_guest_context {
typedef struct vcpu_guest_context vcpu_guest_context_t;
DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
-// dom0 vp op
+/* dom0 vp op */
#define __HYPERVISOR_ia64_dom0vp_op __HYPERVISOR_arch_0
-#define IA64_DOM0VP_ioremap 0 // map io space in machine
- // address to dom0 physical
- // address space.
- // currently physical
- // assignedg address equals to
- // machine address
-#define IA64_DOM0VP_phystomach 1 // 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_machtophys 3 // convert a machine page
- // frame number
- // to the corresponding
- // pseudo physical page frame
- // number of the caller domain
-#define IA64_DOM0VP_zap_physmap 17 // unmap and free pages
- // contained in the specified
- // pseudo physical region
-#define IA64_DOM0VP_add_physmap 18 // assigne machine page frane
- // to dom0's pseudo physical
- // address space.
+/* 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
+
// flags for page assignement to pseudo physical address space
#define _ASSIGN_readonly 0
#define ASSIGN_readonly (1UL << _ASSIGN_readonly)
@@ -370,6 +358,9 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
/* 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)
/* This structure has the same layout of struct ia64_boot_param, defined in
<asm/system.h>. It is redefined here to ease use. */
@@ -395,15 +386,12 @@ struct xen_ia64_boot_param {
#endif /* !__ASSEMBLY__ */
-/* Address of shared_info in domain virtual space.
- This is the default address, for compatibility only. */
-#define XSI_BASE 0xf100000000000000
-
/* 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
@@ -435,6 +423,17 @@ struct xen_ia64_boot_param {
#define HYPERPRIVOP_GET_PSR 0x19
#define HYPERPRIVOP_MAX 0x19
+/* Fast and light hypercalls. */
+#define __HYPERVISOR_ia64_fast_eoi 0x0200
+
+/* Xencomm macros. */
+#define XENCOMM_INLINE_MASK 0xf800000000000000UL
+#define XENCOMM_INLINE_FLAG 0x8000000000000000UL
+
+#define XENCOMM_IS_INLINE(addr) \
+ (((unsigned long)(addr) & XENCOMM_INLINE_MASK) == XENCOMM_INLINE_FLAG)
+#define XENCOMM_INLINE_ADDR(addr) \
+ ((unsigned long)(addr) & ~XENCOMM_INLINE_MASK)
#endif /* __HYPERVISOR_IF_IA64_H__ */
/*