This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / ia64 / xen / hypercall.S
diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S
new file mode 100644 (file)
index 0000000..3996865
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Support routines for Xen hypercalls
+ *
+ * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com>
+ */
+
+#include <asm/processor.h>
+#include <asm/asmmacro.h>
+
+/* To clear vpsr.ic, vpsr.i needs to be cleared first */
+#define XEN_CLEAR_PSR_IC                               \
+       mov r14=1;                                      \
+       movl r15=XSI_PSR_I_ADDR;                        \
+       movl r2=XSI_PSR_IC;                             \
+       ;;                                              \
+       ld8 r15=[r15];                                  \
+       ld4 r3=[r2];                                    \
+       ;;                                              \
+       ld1 r16=[r15];                                  \
+       ;;                                              \
+       st1 [r15]=r14;                                  \
+       st4 [r2]=r0;                                    \
+       ;;
+
+/* First restore vpsr.ic, and then vpsr.i */
+#define XEN_RESTORE_PSR_IC                             \
+       st4 [r2]=r3;                                    \
+       st1 [r15]=r16;                                  \
+       ;;
+
+GLOBAL_ENTRY(xen_get_ivr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=cr.ivr;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_IVR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_get_ivr)
+
+GLOBAL_ENTRY(xen_get_tpr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=cr.tpr;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_TPR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_get_tpr)
+
+GLOBAL_ENTRY(xen_set_tpr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov cr.tpr=r32;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_TPR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_set_tpr)
+
+GLOBAL_ENTRY(xen_eoi)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov cr.eoi=r0;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_EOI
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_eoi)
+
+GLOBAL_ENTRY(xen_thash)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   thash r8=r32;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_THASH
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_thash)
+
+GLOBAL_ENTRY(xen_set_itm)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov cr.itm=r32;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_ITM
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_set_itm)
+
+GLOBAL_ENTRY(xen_ptcga)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   ptc.ga r32,r33;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       mov r9=r33
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_PTC_GA
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_ptcga)
+
+GLOBAL_ENTRY(xen_get_rr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=rr[r32];;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_RR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_get_rr)
+
+GLOBAL_ENTRY(xen_set_rr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov rr[r32]=r33;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       mov r9=r33
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_RR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+       ;;
+END(xen_set_rr)
+
+GLOBAL_ENTRY(xen_set_kr)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.ne p7,p0=r8,r0;;
+(p7)   br.cond.spnt.few 1f;
+       ;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar0=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar1=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar2=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar3=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar4=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar5=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar6=r9
+(p7)   br.ret.sptk.many rp;;
+       cmp.eq p7,p0=r8,r0
+       adds r8=-1,r8;;
+(p7)   mov ar7=r9
+(p7)   br.ret.sptk.many rp;;
+
+1:     mov r8=r32
+       mov r9=r33
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_KR
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_set_kr)
+
+GLOBAL_ENTRY(xen_fc)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   fc r32;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_FC
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_fc)
+
+GLOBAL_ENTRY(xen_get_cpuid)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=cpuid[r32];;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_CPUID
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_get_cpuid)
+
+GLOBAL_ENTRY(xen_get_pmd)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=pmd[r32];;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_PMD
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_get_pmd)
+
+#ifdef CONFIG_IA32_SUPPORT
+GLOBAL_ENTRY(xen_get_eflag)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov r8=ar24;;
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_GET_EFLAG
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_get_eflag)
+       
+// some bits aren't set if pl!=0, see SDM vol1 3.1.8
+GLOBAL_ENTRY(xen_set_eflag)
+       movl r8=running_on_xen;;
+       ld4 r8=[r8];;
+       cmp.eq p7,p0=r8,r0;;
+(p7)   mov ar24=r32
+(p7)   br.ret.sptk.many rp
+       ;;
+       mov r8=r32
+       ;;
+       XEN_CLEAR_PSR_IC
+       ;;
+       XEN_HYPER_SET_EFLAG
+       ;;
+       XEN_RESTORE_PSR_IC
+       ;;
+       br.ret.sptk.many rp
+END(xen_set_eflag)
+#endif
+
+GLOBAL_ENTRY(xen_send_ipi)
+        mov r14=r32
+        mov r15=r33
+        mov r2=0x400
+        break 0x1000
+        ;;
+        br.ret.sptk.many rp
+        ;;
+END(xen_send_ipi)
+
+#ifdef CONFIG_XEN_IA64_VDSO_PARAVIRT
+// Those are vdso specialized.
+// In fsys mode, call, ret can't be used.
+GLOBAL_ENTRY(xen_rsm_be_i)
+       ld8 r22=[r22]
+       ;; 
+       st1 [r22]=r20
+       st4 [r23]=r0
+       XEN_HYPER_RSM_BE
+       st4 [r23]=r20
+       brl.cond.sptk   .vdso_rsm_be_i_ret
+       ;; 
+END(xen_rsm_be_i)
+
+GLOBAL_ENTRY(xen_get_psr)
+       mov r31=r8
+       mov r25=IA64_PSR_IC
+       st4 [r23]=r0
+       XEN_HYPER_GET_PSR
+       ;; 
+       st4 [r23]=r20
+       or r29=r8,r25 // vpsr.ic was cleared for hyperprivop
+       mov r8=r31
+       brl.cond.sptk   .vdso_get_psr_ret
+       ;; 
+END(xen_get_psr)
+
+       // see xen_ssm_i() in privop.h
+       // r22 = &vcpu->evtchn_mask
+       // r23 = &vpsr.ic
+       // r24 = &vcpu->pending_interruption
+       // r25 = tmp
+       // r31 = tmp
+       // p11 = tmp
+       // p14 = tmp
+#define XEN_SET_PSR_I                  \
+       ld4 r31=[r22];                  \
+       ld4 r25=[r24];                  \
+       ;;                              \
+       st4 [r22]=r0;                   \
+       cmp.ne.unc p14,p0=r0,r31;       \
+       ;;                              \
+(p14)  cmp.ne.unc p11,p0=r0,r25;       \
+       ;;                              \
+(p11)  st4 [r22]=r20;                  \
+(p11)  st4 [r23]=r0;                   \
+(p11)  XEN_HYPER_SSM_I;
+               
+GLOBAL_ENTRY(xen_ssm_i_0)
+       XEN_SET_PSR_I
+       brl.cond.sptk   .vdso_ssm_i_0_ret
+       ;; 
+END(xen_ssm_i_0)
+
+GLOBAL_ENTRY(xen_ssm_i_1)
+       XEN_SET_PSR_I
+       brl.cond.sptk   .vdso_ssm_i_1_ret
+       ;; 
+END(xen_ssm_i_1)
+#endif