aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorJes Sorensen <jes@sgi.com>2009-02-25 11:38:55 -0500
committerAvi Kivity <avi@redhat.com>2009-06-10 04:48:29 -0400
commit0b5d7a2ccb98f0403b1969295429724af9dc9d8e (patch)
tree56108639641d6634df4a1de4e3ef4d4b9589a26b /arch/ia64
parentce17c643738bebcacf8d19d8cab7dd3eb96f9f32 (diff)
KVM: ia64: Drop in SN2 replacement of fast path ITC emulation fault handler
Copy in SN2 RTC based ITC emulation for fast exit. The two versions have the same size, so a dropin is simpler than patching the branch instruction to hit the SN2 version. Signed-off-by: Jes Sorensen <jes@sgi.com> Acked-by: Xiantao Zhang <xiantao.zhang@intel.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/include/asm/kvm_host.h2
-rw-r--r--arch/ia64/kvm/kvm-ia64.c32
-rw-r--r--arch/ia64/kvm/optvfault.S30
-rw-r--r--arch/ia64/kvm/vmm.c12
4 files changed, 71 insertions, 5 deletions
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h
index 12439956551b..589536fa799d 100644
--- a/arch/ia64/include/asm/kvm_host.h
+++ b/arch/ia64/include/asm/kvm_host.h
@@ -580,6 +580,8 @@ struct kvm_vmm_info{
580 kvm_vmm_entry *vmm_entry; 580 kvm_vmm_entry *vmm_entry;
581 kvm_tramp_entry *tramp_entry; 581 kvm_tramp_entry *tramp_entry;
582 unsigned long vmm_ivt; 582 unsigned long vmm_ivt;
583 unsigned long patch_mov_ar;
584 unsigned long patch_mov_ar_sn2;
583}; 585};
584 586
585int kvm_highest_pending_irq(struct kvm_vcpu *vcpu); 587int kvm_highest_pending_irq(struct kvm_vcpu *vcpu);
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index ebbd995194fb..4623a90e515a 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1671,8 +1671,37 @@ out:
1671 return 0; 1671 return 0;
1672} 1672}
1673 1673
1674
1675/*
1676 * On SN2, the ITC isn't stable, so copy in fast path code to use the
1677 * SN2 RTC, replacing the ITC based default verion.
1678 */
1679static void kvm_patch_vmm(struct kvm_vmm_info *vmm_info,
1680 struct module *module)
1681{
1682 unsigned long new_ar, new_ar_sn2;
1683 unsigned long module_base;
1684
1685 if (!ia64_platform_is("sn2"))
1686 return;
1687
1688 module_base = (unsigned long)module->module_core;
1689
1690 new_ar = kvm_vmm_base + vmm_info->patch_mov_ar - module_base;
1691 new_ar_sn2 = kvm_vmm_base + vmm_info->patch_mov_ar_sn2 - module_base;
1692
1693 printk(KERN_INFO "kvm: Patching ITC emulation to use SGI SN2 RTC "
1694 "as source\n");
1695
1696 /*
1697 * Copy the SN2 version of mov_ar into place. They are both
1698 * the same size, so 6 bundles is sufficient (6 * 0x10).
1699 */
1700 memcpy((void *)new_ar, (void *)new_ar_sn2, 0x60);
1701}
1702
1674static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info, 1703static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
1675 struct module *module) 1704 struct module *module)
1676{ 1705{
1677 unsigned long module_base; 1706 unsigned long module_base;
1678 unsigned long vmm_size; 1707 unsigned long vmm_size;
@@ -1694,6 +1723,7 @@ static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
1694 return -EFAULT; 1723 return -EFAULT;
1695 1724
1696 memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size); 1725 memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size);
1726 kvm_patch_vmm(vmm_info, module);
1697 kvm_flush_icache(kvm_vmm_base, vmm_size); 1727 kvm_flush_icache(kvm_vmm_base, vmm_size);
1698 1728
1699 /*Recalculate kvm_vmm_info based on new VMM*/ 1729 /*Recalculate kvm_vmm_info based on new VMM*/
diff --git a/arch/ia64/kvm/optvfault.S b/arch/ia64/kvm/optvfault.S
index 32254ce9a1bd..f793be3effff 100644
--- a/arch/ia64/kvm/optvfault.S
+++ b/arch/ia64/kvm/optvfault.S
@@ -11,6 +11,7 @@
11 11
12#include <asm/asmmacro.h> 12#include <asm/asmmacro.h>
13#include <asm/processor.h> 13#include <asm/processor.h>
14#include <asm/kvm_host.h>
14 15
15#include "vti.h" 16#include "vti.h"
16#include "asm-offsets.h" 17#include "asm-offsets.h"
@@ -140,6 +141,35 @@ GLOBAL_ENTRY(kvm_asm_mov_from_ar)
140 ;; 141 ;;
141END(kvm_asm_mov_from_ar) 142END(kvm_asm_mov_from_ar)
142 143
144/*
145 * Special SGI SN2 optimized version of mov_from_ar using the SN2 RTC
146 * clock as it's source for emulating the ITC. This version will be
147 * copied on top of the original version if the host is determined to
148 * be an SN2.
149 */
150GLOBAL_ENTRY(kvm_asm_mov_from_ar_sn2)
151 add r18=VMM_VCPU_ITC_OFS_OFFSET, r21
152 movl r19 = (KVM_VMM_BASE+(1<<KVM_VMM_SHIFT))
153
154 add r16=VMM_VCPU_LAST_ITC_OFFSET,r21
155 extr.u r17=r25,6,7
156 mov r24=b0
157 ;;
158 ld8 r18=[r18]
159 ld8 r19=[r19]
160 addl r20=@gprel(asm_mov_to_reg),gp
161 ;;
162 add r19=r19,r18
163 shladd r17=r17,4,r20
164 ;;
165 adds r30=kvm_resume_to_guest-asm_mov_to_reg,r20
166 st8 [r16] = r19
167 mov b0=r17
168 br.sptk.few b0
169 ;;
170END(kvm_asm_mov_from_ar_sn2)
171
172
143 173
144// mov r1=rr[r3] 174// mov r1=rr[r3]
145GLOBAL_ENTRY(kvm_asm_mov_from_rr) 175GLOBAL_ENTRY(kvm_asm_mov_from_rr)
diff --git a/arch/ia64/kvm/vmm.c b/arch/ia64/kvm/vmm.c
index 9eee5c04bacc..f4b4c899bb6c 100644
--- a/arch/ia64/kvm/vmm.c
+++ b/arch/ia64/kvm/vmm.c
@@ -30,15 +30,19 @@ MODULE_AUTHOR("Intel");
30MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
31 31
32extern char kvm_ia64_ivt; 32extern char kvm_ia64_ivt;
33extern char kvm_asm_mov_from_ar;
34extern char kvm_asm_mov_from_ar_sn2;
33extern fpswa_interface_t *vmm_fpswa_interface; 35extern fpswa_interface_t *vmm_fpswa_interface;
34 36
35long vmm_sanity = 1; 37long vmm_sanity = 1;
36 38
37struct kvm_vmm_info vmm_info = { 39struct kvm_vmm_info vmm_info = {
38 .module = THIS_MODULE, 40 .module = THIS_MODULE,
39 .vmm_entry = vmm_entry, 41 .vmm_entry = vmm_entry,
40 .tramp_entry = vmm_trampoline, 42 .tramp_entry = vmm_trampoline,
41 .vmm_ivt = (unsigned long)&kvm_ia64_ivt, 43 .vmm_ivt = (unsigned long)&kvm_ia64_ivt,
44 .patch_mov_ar = (unsigned long)&kvm_asm_mov_from_ar,
45 .patch_mov_ar_sn2 = (unsigned long)&kvm_asm_mov_from_ar_sn2,
42}; 46};
43 47
44static int __init kvm_vmm_init(void) 48static int __init kvm_vmm_init(void)