fw.s
来自「xen虚拟机源代码安装包」· S 代码 · 共 541 行
S
541 行
/* * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> * Parts taken from FreeBSD. * *************************************************************************** * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#include "asm.h"#include "page.h"#include "ia64_cpu.h"#include "ia64_fpu.h"#include "offsets.h"#include "xen/xen.h"/* * ia64_change_mode: change mode to/from physical mode * * Arguments: * r14 psr for desired mode * * Modifies: * r15-r20 scratch * ar.bsp translated to new mode * sp translated to new mode * iip translated to new mode */ENTRY(ia64_change_mode) rsm psr.i | psr.ic mov r19=ar.rsc // save rsc while we change mode tbit.nz p8,p9=r14,17 // Uses psr.dt-physical or virtual ? // p8 == true: switch to virtual // p9 == true: switch to physical ;; mov ar.rsc=IA64_RSE_LAZY // turn off RSE mov r16=rp ;; flushrs // clean the rse srlz.i ;;1: mov r15=ip mov r17=ar.bsp mov r18=ar.rnat ;; add r15=2f-1b,r15 // address to rfi to /* !!! must be the same like in minios-ia64.lds */(p8) movl r20=(KERNEL_START - (1<<KERNEL_PHYS_START_SHIFT)) ;; // (p8): switch to virtual // (p9): switch to physical // from virtual to physical(p9) tpa r15=r15 // ip(p9) tpa r16=r16 // rp(p9) tpa r17=r17 // ar.bsp(p9) tpa sp=sp // sp ;; /* Needed only for assembler violate ... warnings. */ // from physical to virtual(p8) add r15=r20,r15 // ip(p8) add r16=r20,r16 // rp(p8) add r17=r20,r17 // ar.bsp(p8) add sp=r20,sp // sp ;; mov ar.bspstore=r17 mov rp=r16 ;; mov ar.rnat=r18 mov cr.iip=r15 mov cr.ipsr=r14 // psr for new mode mov cr.ifs=r0 ;; rfi ;;2: mov ar.rsc=r19 // restore ar.rsc ;; br.ret.sptk.few rp // now in new modeEND(ia64_change_mode)/* * ia64_physical_mode: change mode to physical mode * * Return: * ret0 psr to restore * * Modifies: * r15-r18 scratch * ar.bsp tranlated to physical mode * psr.i cleared */ENTRY(ia64_physical_mode) mov r14=psr movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT| \ IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH) ;; mov ret0=r14 movl r16=IA64_PSR_BN ;; andcm r14=r14,r15 // clear various xT bits ;; or r14=r14,r16 // make sure BN=1 or ret0=ret0,r16 // make sure BN=1 ;; br.cond.sptk.many ia64_change_modeEND(ia64_physical_mode)/* * ia64_call_efi_physical: call an EFI procedure in physical mode * * Arguments: * in0 Address of EFI procedure descriptor * in1-in5 Arguments to EFI procedure * * Return: * ret0-ret3 return values from EFI * */ENTRY(ia64_call_efi_physical) .prologue .regstk 6,4,5,0 .save ar.pfs,loc0 alloc loc0=ar.pfs,6,4,5,0 ;; .save rp,loc1 mov loc1=rp ;; .body br.call.sptk.many rp=ia64_physical_mode ;; mov loc2=r8 // psr to restore mode mov loc3=gp // save kernel gp ld8 r14=[in0],8 // function address ;; ld8 gp=[in0] // function gp value#if defined(BIG_ENDIAN) mux1 r14=r14,@rev // swap because mini-os is in BE mov ar.rsc=3 ;;#endif mov out0=in1 mov out1=in2 mov out2=in3 mov out3=in4 mov out4=in5 mov b6=r14 ;;#if defined(BIG_ENDIAN) mux1 gp=gp,@rev // swap because mini-os is in BE rum IA64_PSR_BE ;;#endif br.call.sptk.many rp=b6 // call EFI procedure#if defined(BIG_ENDIAN) ;; sum IA64_PSR_BE mov ar.rsc=IA64_RSE_EAGER#endif mov gp=loc3 // restore kernel gp mov r14=loc2 // psr to restore mode ;; br.call.sptk.many rp=ia64_change_mode ;; mov rp=loc1 mov ar.pfs=loc0 ;; br.ret.sptk.many rpEND(ia64_call_efi_physical) /* * struct ia64_pal_result ia64_call_pal_static(uint64_t proc, * uint64_t arg1, uint64_t arg2, uint64_t arg3) */ENTRY(ia64_call_pal_static) .regstk 4,5,0,0palret = loc0entry = loc1rpsave = loc2pfssave = loc3psrsave = loc4 alloc pfssave=ar.pfs,4,5,0,0 ;; mov rpsave=rp movl entry=@gprel(ia64_pal_entry)1: mov palret=ip // for return address ;; add entry=entry,gp mov psrsave=psr mov r28=in0 // procedure number ;; ld8 entry=[entry] // read entry point mov r29=in1 // copy arguments mov r30=in2 mov r31=in3 ;; mov b6=entry add palret=2f-1b,palret // calculate return address ;; mov b0=palret rsm psr.i // disable interrupts ;;#if defined(BIG_ENDIAN) rum IA64_PSR_BE // set psr.be==0 ;;#endif br.cond.sptk b6 // call into firmware ;;#if defined(BIG_ENDIAN) sum IA64_PSR_BE // set psr.be==1 ;;#endif ssm psr.i // enable interrupts ;;2: mov psr.l=psrsave mov rp=rpsave mov ar.pfs=pfssave ;; srlz.d br.ret.sptk rpEND(ia64_call_pal_static)/* * Call a efi function. * in0: func descriptor * in1: param1 * ... * in5: param5 */ENTRY(ia64_call_efi_func) alloc loc0=ar.pfs,6,3,5,0 mov loc1=gp mov loc2=rp mov out0=in1 mov out1=in2 mov out2=in3 mov out3=in4 mov out4=in5 ld8 r14=[in0],8 // get function address ;; ld8 gp=[in0] // function gp value ;;#if defined(BIG_ENDIAN) mux1 r14=r14,@rev // swap if mini-os is in BE mux1 gp=gp,@rev // swap if mini-os is in BE#endif ;; mov b6=r14#if defined(BIG_ENDIAN) rum IA64_PSR_BE ;;#endif br.call.sptk.many rp=b6 // call EFI procedure #if defined(BIG_ENDIAN) sum IA64_PSR_BE ;;#endif mov ar.pfs=loc0 mov gp=loc1 mov rp=loc2 br.ret.sptk rpEND(ia64_call_efi_func)/* Restore the context from the thread context. */ENTRY(restore_context){ .mmi invala mov ar.rsc=IA64_RSE_LAZY add r29=SW_SP,in0} add r30=SW_RP,in0 add r31=SW_PR,in0 ;; ld8 r12=[r29],SW_LC-SW_SP // load sp ld8 r16=[r30],SW_BSP-SW_RP // load rp ;; ld8 r17=[r31],SW_RNAT-SW_PR // load pr ld8 r18=[r30],SW_PFS-SW_BSP // load bsp mov rp=r16 ;; ld8 r16=[r31],SW_R4-SW_RNAT // load rnat mov pr=r17,-1 // set pr mov ar.bspstore=r18 ;; ld8 r18=[r30],SW_UNATA-SW_PFS // load pfs ld8 r17=[r29],SW_UNATB-SW_LC // load lc mov ar.rnat=r16 ;; ld8 r16=[r30],SW_R5-SW_UNATA // load unat_a mov ar.pfs=r18 mov ar.lc=r17 ;; ld8.fill r4=[r31],SW_R6-SW_R4 // load r4 mov ar.unat=r16 ;; ld8.fill r5=[r30],SW_R7-SW_R5 // load r5 ld8 r16=[r29],SW_B3-SW_UNATB // load unat_b mov ar.rsc=IA64_RSE_EAGER ;; ld8.fill r6=[r31],SW_B1-SW_R6 // load r6 ld8.fill r7=[r30],SW_B2-SW_R7 // load r7 ;; ld8 r17=[r31],SW_B4-SW_B1 // load b1 ld8 r18=[r30],SW_B5-SW_B2 // load b2 mov ar.unat=r16 // unat_b ;; ld8 r16=[r29],SW_F2-SW_B3 // load b3 mov b1=r17 mov b2=r18 ;; ld8 r17=[r31],SW_F3-SW_B4 // load b4 ld8 r18=[r30],SW_F4-SW_B5 // load b5 mov b3=r16 ;; ldf.fill f2=[r29] // load f2 mov b4=r17 mov b5=r18 ;; ldf.fill f3=[r31],SW_F5-SW_F3 // load f3 ldf.fill f4=[r30],SW_F4-SW_F2 // load f4 ;; ldf.fill f5=[r31],SW_F5-SW_F3 // load f5 ldf.fill f16=[r30],SW_F4-SW_F2 // load f16 ;; ldf.fill f17=[r31],SW_F5-SW_F3 // load f17 ldf.fill f18=[r30],SW_F4-SW_F2 // load f18 ;; ldf.fill f19=[r31],SW_F5-SW_F3 // load f19 ldf.fill f20=[r30],SW_F4-SW_F2 // load f20 ;; ldf.fill f21=[r31],SW_F5-SW_F3 // load f21 ldf.fill f22=[r30],SW_F4-SW_F2 // load f22 ;; ldf.fill f23=[r31],SW_F5-SW_F3 // load f23 ldf.fill f24=[r30],SW_F4-SW_F2 // load f24 ;; ldf.fill f25=[r31],SW_F5-SW_F3 // load f25 ldf.fill f26=[r30],SW_F4-SW_F2 // load f26 ;; ldf.fill f27=[r31],SW_F5-SW_F3 // load f27 ldf.fill f28=[r30],SW_F4-SW_F2 // load f28 ;; ldf.fill f29=[r31],SW_F5-SW_F3 // load f29 ldf.fill f30=[r30],SW_F4-SW_F2 // load f30 ;; ldf.fill f31=[r30],SW_F4-SW_F2 // load f31 add r8=1,r0 br.ret.sptk rp ;;END(restore_context)/* * void switch_context(struct thread* old, struct thread* new) */ENTRY(switch_context) mov ar.rsc=IA64_RSE_LAZY mov r16=ar.unat add r31=SW_UNATB,in0 add r30=SW_SP,in0 ;;{ .mmi flushrs st8 [r30]=sp,SW_RP-SW_SP // sp mov r17=rp ;;} st8 [r31]=r16,SW_PR-SW_UNATB // unat (before) st8 [r30]=r17,SW_BSP-SW_RP // rp mov r16=pr ;; st8 [r31]=r16,SW_PFS-SW_PR // pr mov r17=ar.bsp mov r16=ar.pfs ;; st8 [r31]=r16,SW_RNAT-SW_PFS // save pfs st8 [r30]=r17,SW_R4-SW_BSP // save bsp mov r16=ar.rnat ;; st8 [r31]=r16,SW_R5-SW_RNAT // save rnat mov ar.rsc=IA64_RSE_EAGER ;;{ .mmi .mem.offset 8,0 st8.spill [r30]=r4,SW_R6-SW_R4 // r4 .mem.offset 16,0 st8.spill [r31]=r5,SW_R7-SW_R5 // r5 mov r16=b1 ;;}{ .mmi .mem.offset 8,0 st8.spill [r30]=r4,SW_B1-SW_R6 // r6 .mem.offset 16,0 st8.spill [r31]=r5,SW_B2-SW_R7 // r7 mov r17=b2 ;;} st8 [r30]=r16,SW_UNATA-SW_B1 // b1 st8 [r31]=r17,SW_B3-SW_B2 // b2 mov r18=ar.unat mov r19=b3 mov r20=b4 mov r21=b5 ;; st8 [r30]=r18,SW_B4-SW_UNATA // unat (after) st8 [r31]=r19,SW_B5-SW_B3 // b3 ;; st8 [r30]=r20,SW_LC-SW_B4 // b4 st8 [r31]=r21,SW_F2-SW_B5 // b5 mov r17=ar.lc ;; st8 [r30]=r17,SW_F3-SW_LC // ar.lc stf.spill [r31]=f2,SW_F4-SW_F2 ;; stf.spill [r30]=f3,SW_F5-SW_F3 stf.spill [r31]=f4,SW_F4-SW_F2 ;; stf.spill [r30]=f5,SW_F5-SW_F3 stf.spill [r31]=f16,SW_F4-SW_F2 ;; stf.spill [r30]=f17,SW_F5-SW_F3 stf.spill [r31]=f18,SW_F4-SW_F2 ;; stf.spill [r30]=f19,SW_F5-SW_F3 stf.spill [r31]=f20,SW_F4-SW_F2 ;; stf.spill [r30]=f21,SW_F5-SW_F3 stf.spill [r31]=f22,SW_F4-SW_F2 ;; stf.spill [r30]=f23,SW_F5-SW_F3 stf.spill [r31]=f24,SW_F4-SW_F2 ;; stf.spill [r30]=f25,SW_F5-SW_F3 stf.spill [r31]=f26,SW_F4-SW_F2 ;; stf.spill [r30]=f27,SW_F5-SW_F3 stf.spill [r31]=f28,SW_F4-SW_F2 ;; stf.spill [r30]=f29,SW_F4-SW_F2 stf.spill [r31]=f30 ;; stf.spill [r30]=f31 add r8=0,r0 mf// br.ret.sptk rp{ .mfb mov r32=r33 nop 0 br.sptk restore_context ;;}END(switch_context)/* * The function is used to start a new thread. */ENTRY(thread_starter) .prologue .save ar.pfs,loc0 alloc loc0=ar.pfs,0,1,1,0 ;; .body ;; mov b7=r4 // the function pointer mov out0=r6 // the argument ;; br.call.sptk.many rp=b7 // Call the thread function ;; br.call.sptk.many rp=exit_thread // call exit_thread ;;END(thread_starter)ENTRY(__hypercall) mov r2=r37 break 0x1000 br.ret.sptk.many b0 ;;END(__hypercall)/* * Stub for suspend. * Just force the stacked registers to be written in memory. */ENTRY(xencomm_arch_hypercall_suspend) ;; alloc r20=ar.pfs,0,0,6,0 mov r2=__HYPERVISOR_sched_op ;; /* We don't want to deal with RSE. */ flushrs mov r33=r32 mov r32=2 // SCHEDOP_shutdown ;; break 0x1000 ;; br.ret.sptk.many b0END(xencomm_arch_hypercall_suspend)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?