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@xxxxxxx> --- arch/ia64/include/asm/kvm_host.h | 2 ++ arch/ia64/kvm/kvm-ia64.c | 32 +++++++++++++++++++++++++++++++- arch/ia64/kvm/optvfault.S | 30 ++++++++++++++++++++++++++++++ arch/ia64/kvm/vmm.c | 12 ++++++++---- 4 files changed, 71 insertions(+), 5 deletions(-) Index: linux-2.6.git/arch/ia64/include/asm/kvm_host.h =================================================================== --- linux-2.6.git.orig/arch/ia64/include/asm/kvm_host.h +++ linux-2.6.git/arch/ia64/include/asm/kvm_host.h @@ -599,6 +599,8 @@ kvm_vmm_entry *vmm_entry; kvm_tramp_entry *tramp_entry; unsigned long vmm_ivt; + unsigned long patch_mov_ar; + unsigned long patch_mov_ar_sn2; }; int kvm_highest_pending_irq(struct kvm_vcpu *vcpu); Index: linux-2.6.git/arch/ia64/kvm/kvm-ia64.c =================================================================== --- linux-2.6.git.orig/arch/ia64/kvm/kvm-ia64.c +++ linux-2.6.git/arch/ia64/kvm/kvm-ia64.c @@ -1591,8 +1591,37 @@ return 0; } + +/* + * On SN2, the ITC isn't stable, so copy in fast path code to use the + * SN2 RTC, replacing the ITC based default verion. + */ +static void kvm_patch_vmm(struct kvm_vmm_info *vmm_info, + struct module *module) +{ + unsigned long new_ar, new_ar_sn2; + unsigned long module_base; + + if (!ia64_platform_is("sn2")) + return; + + module_base = (unsigned long)module->module_core; + + new_ar = kvm_vmm_base + vmm_info->patch_mov_ar - module_base; + new_ar_sn2 = kvm_vmm_base + vmm_info->patch_mov_ar_sn2 - module_base; + + printk(KERN_INFO "kvm: Patching ITC emulation to use SGI SN2 RTC " + "as source\n"); + + /* + * Copy the SN2 version of mov_ar into place. They are both + * the same size, so 6 bundles is sufficient (6 * 0x10). + */ + memcpy((void *)new_ar, (void *)new_ar_sn2, 0x60); +} + static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info, - struct module *module) + struct module *module) { unsigned long module_base; unsigned long vmm_size; @@ -1614,6 +1643,7 @@ return -EFAULT; memcpy((void *)kvm_vmm_base, (void *)module_base, vmm_size); + kvm_patch_vmm(vmm_info, module); kvm_flush_icache(kvm_vmm_base, vmm_size); /*Recalculate kvm_vmm_info based on new VMM*/ Index: linux-2.6.git/arch/ia64/kvm/optvfault.S =================================================================== --- linux-2.6.git.orig/arch/ia64/kvm/optvfault.S +++ linux-2.6.git/arch/ia64/kvm/optvfault.S @@ -11,6 +11,7 @@ #include <asm/asmmacro.h> #include <asm/processor.h> +#include <asm/kvm_host.h> #include "vti.h" #include "asm-offsets.h" @@ -140,6 +141,35 @@ ;; END(kvm_asm_mov_from_ar) +/* + * Special SGI SN2 optimized version of mov_from_ar using the SN2 RTC + * clock as it's source for emulating the ITC. This version will be + * copied on top of the original version if the host is determined to + * be an SN2. + */ +GLOBAL_ENTRY(kvm_asm_mov_from_ar_sn2) + add r18=VMM_VCPU_ITC_OFS_OFFSET, r21 + movl r19 = (KVM_VMM_BASE+(1<<KVM_VMM_SHIFT)) + + add r16=VMM_VCPU_LAST_ITC_OFFSET,r21 + extr.u r17=r25,6,7 + mov r24=b0 + ;; + ld8 r18=[r18] + ld8 r19=[r19] + addl r20=@gprel(asm_mov_to_reg),gp + ;; + add r19=r19,r18 + shladd r17=r17,4,r20 + ;; + adds r30=kvm_resume_to_guest-asm_mov_to_reg,r20 + st8 [r16] = r19 + mov b0=r17 + br.sptk.few b0 + ;; +END(kvm_asm_mov_from_ar_sn2) + + // mov r1=rr[r3] GLOBAL_ENTRY(kvm_asm_mov_from_rr) Index: linux-2.6.git/arch/ia64/kvm/vmm.c =================================================================== --- linux-2.6.git.orig/arch/ia64/kvm/vmm.c +++ linux-2.6.git/arch/ia64/kvm/vmm.c @@ -30,15 +30,19 @@ MODULE_LICENSE("GPL"); extern char kvm_ia64_ivt; +extern char kvm_asm_mov_from_ar; +extern char kvm_asm_mov_from_ar_sn2; extern fpswa_interface_t *vmm_fpswa_interface; long vmm_sanity = 1; struct kvm_vmm_info vmm_info = { - .module = THIS_MODULE, - .vmm_entry = vmm_entry, - .tramp_entry = vmm_trampoline, - .vmm_ivt = (unsigned long)&kvm_ia64_ivt, + .module = THIS_MODULE, + .vmm_entry = vmm_entry, + .tramp_entry = vmm_trampoline, + .vmm_ivt = (unsigned long)&kvm_ia64_ivt, + .patch_mov_ar = (unsigned long)&kvm_asm_mov_from_ar, + .patch_mov_ar_sn2 = (unsigned long)&kvm_asm_mov_from_ar_sn2, }; static int __init kvm_vmm_init(void) -- To unsubscribe from this list: send the line "unsubscribe kvm-ia64" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html