diff options
author | Jes Sorensen <jes@sgi.com> | 2009-02-25 11:38:55 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-06-10 04:48:29 -0400 |
commit | 0b5d7a2ccb98f0403b1969295429724af9dc9d8e (patch) | |
tree | 56108639641d6634df4a1de4e3ef4d4b9589a26b /arch | |
parent | ce17c643738bebcacf8d19d8cab7dd3eb96f9f32 (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')
-rw-r--r-- | arch/ia64/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 32 | ||||
-rw-r--r-- | arch/ia64/kvm/optvfault.S | 30 | ||||
-rw-r--r-- | arch/ia64/kvm/vmm.c | 12 |
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 | ||
585 | int kvm_highest_pending_irq(struct kvm_vcpu *vcpu); | 587 | int 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 | */ | ||
1679 | static 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 | |||
1674 | static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info, | 1703 | static 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 | ;; |
141 | END(kvm_asm_mov_from_ar) | 142 | END(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 | */ | ||
150 | GLOBAL_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 | ;; | ||
170 | END(kvm_asm_mov_from_ar_sn2) | ||
171 | |||
172 | |||
143 | 173 | ||
144 | // mov r1=rr[r3] | 174 | // mov r1=rr[r3] |
145 | GLOBAL_ENTRY(kvm_asm_mov_from_rr) | 175 | GLOBAL_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"); | |||
30 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
31 | 31 | ||
32 | extern char kvm_ia64_ivt; | 32 | extern char kvm_ia64_ivt; |
33 | extern char kvm_asm_mov_from_ar; | ||
34 | extern char kvm_asm_mov_from_ar_sn2; | ||
33 | extern fpswa_interface_t *vmm_fpswa_interface; | 35 | extern fpswa_interface_t *vmm_fpswa_interface; |
34 | 36 | ||
35 | long vmm_sanity = 1; | 37 | long vmm_sanity = 1; |
36 | 38 | ||
37 | struct kvm_vmm_info vmm_info = { | 39 | struct 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 | ||
44 | static int __init kvm_vmm_init(void) | 48 | static int __init kvm_vmm_init(void) |