📄 hyperprivop.s
字号:
/* * arch/ia64/kernel/hyperprivop.S * * Copyright (C) 2005 Hewlett-Packard Co * Dan Magenheimer <dan.magenheimer@hp.com> */#include <linux/config.h>#include <asm/asmmacro.h>#include <asm/kregs.h>#include <asm/offsets.h>#include <asm/processor.h>#include <asm/system.h>#include <asm/debugger.h>#include <asm/asm-xsi-offsets.h>#include <asm/pgtable.h>#include <asm/vmmu.h>#include <public/xen.h>#define PAGE_PHYS (__DIRTY_BITS | _PAGE_PL_PRIV | _PAGE_AR_RWX)#if 1 // change to 0 to turn off all fast paths# define FAST_HYPERPRIVOPS# ifdef PERF_COUNTERS# define FAST_HYPERPRIVOP_CNT# define FAST_HYPERPRIVOP_PERFC(N) PERFC(fast_hyperprivop + N)# define FAST_REFLECT_CNT# endif //#define FAST_TICK // mostly working (unat problems) but default off for now//#define FAST_TLB_MISS_REFLECT // mostly working but default off for now# undef FAST_ITC //XXX TODO fast_itc doesn't support dom0 vp yet# define FAST_BREAK# undef FAST_ACCESS_REFLECT //XXX TODO fast_access_reflect // doesn't support dom0 vp yet.# define FAST_RFI// TODO: Since we use callback to deliver interrupt, // FAST_SSM_I needs to be rewritten.# define FAST_SSM_I# define FAST_PTC_GA# undef RFI_TO_INTERRUPT // not working yet# define FAST_SET_RR0_TO_RR4#endif#ifdef CONFIG_SMP //#warning "FIXME: ptc.ga instruction requires spinlock for SMP" #undef FAST_PTC_GA#endif// FIXME: turn off for now... but NaTs may crash Xen so re-enable soon!#define HANDLE_AR_UNAT// FIXME: This is defined in include/asm-ia64/hw_irq.h but this// doesn't appear to be include'able from assembly?#define IA64_TIMER_VECTOR 0xef// Note: not hand-scheduled for now// Registers at entry// r16 == cr.isr// r17 == cr.iim// r18 == XSI_PSR_IC_OFS// r19 == ipsr.cpl// r31 == prGLOBAL_ENTRY(fast_hyperprivop) // HYPERPRIVOP_SSM_I? // assumes domain interrupts pending, so just do it cmp.eq p7,p6=HYPERPRIVOP_SSM_I,r17(p7) br.sptk.many hyper_ssm_i;; // Check pending event indication adds r20=XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS, r18;; ld8 r20=[r20] ;; ld1 r22=[r20],-1 // evtchn_upcall_mask ;; ld1 r20=[r20] // evtchn_upcall_pending ;; // HYPERPRIVOP_RFI? cmp.eq p7,p6=HYPERPRIVOP_RFI,r17(p7) br.sptk.many hyper_rfi ;;#ifndef FAST_HYPERPRIVOPS // see beginning of file br.sptk.many dispatch_break_fault ;;#endif // if event enabled and there are pending events cmp.ne p7,p0=r20,r0 ;; cmp.eq.and p7,p0=r22,r0(p7) br.spnt.many dispatch_break_fault ;; // HYPERPRIVOP_COVER? cmp.eq p7,p0=HYPERPRIVOP_COVER,r17(p7) br.sptk.many hyper_cover ;; // HYPERPRIVOP_SSM_DT? cmp.eq p7,p0=HYPERPRIVOP_SSM_DT,r17(p7) br.sptk.many hyper_ssm_dt ;; // HYPERPRIVOP_RSM_DT? cmp.eq p7,p0=HYPERPRIVOP_RSM_DT,r17(p7) br.sptk.many hyper_rsm_dt ;; // HYPERPRIVOP_SET_ITM? cmp.eq p7,p0=HYPERPRIVOP_SET_ITM,r17(p7) br.sptk.many hyper_set_itm ;; // HYPERPRIVOP_SET_RR0_TO_RR4? cmp.eq p7,p0=HYPERPRIVOP_SET_RR0_TO_RR4,r17(p7) br.sptk.many hyper_set_rr0_to_rr4 ;; // HYPERPRIVOP_SET_RR? cmp.eq p7,p0=HYPERPRIVOP_SET_RR,r17(p7) br.sptk.many hyper_set_rr ;; // HYPERPRIVOP_GET_RR? cmp.eq p7,p0=HYPERPRIVOP_GET_RR,r17(p7) br.sptk.many hyper_get_rr ;; // HYPERPRIVOP_GET_PSR? cmp.eq p7,p0=HYPERPRIVOP_GET_PSR,r17(p7) br.sptk.many hyper_get_psr ;; // HYPERPRIVOP_PTC_GA? cmp.eq p7,p0=HYPERPRIVOP_PTC_GA,r17(p7) br.sptk.many hyper_ptc_ga ;; // HYPERPRIVOP_ITC_D? cmp.eq p7,p0=HYPERPRIVOP_ITC_D,r17(p7) br.sptk.many hyper_itc_d ;; // HYPERPRIVOP_ITC_I? cmp.eq p7,p0=HYPERPRIVOP_ITC_I,r17(p7) br.sptk.many hyper_itc_i ;; // HYPERPRIVOP_THASH? cmp.eq p7,p0=HYPERPRIVOP_THASH,r17(p7) br.sptk.many hyper_thash ;; // HYPERPRIVOP_SET_KR? cmp.eq p7,p0=HYPERPRIVOP_SET_KR,r17(p7) br.sptk.many hyper_set_kr ;; // if not one of the above, give up for now and do it the slow way br.sptk.many dispatch_break_fault ;;END(fast_hyperprivop)// give up for now if: ipsr.be==1, ipsr.pp==1// from reflect_interruption, don't need to:// - printk first extint (debug only)// - check for interrupt collection enabled (routine will force on)// - set ifa (not valid for extint)// - set iha (not valid for extint)// - set itir (not valid for extint)// DO need to// - increment the HYPER_SSM_I fast_hyperprivop counter// - set shared_mem iip to instruction after HYPER_SSM_I// - set cr.iip to guest iva+0x3000// - set shared_mem ipsr to [vcpu_get_ipsr_int_state]// be = pp = bn = 0; dt = it = rt = 1; cpl = 3 or 0;// i = shared_mem interrupt_delivery_enabled// ic = shared_mem interrupt_collection_enabled// ri = instruction after HYPER_SSM_I// all other bits unchanged from real cr.ipsr// - set cr.ipsr (DELIVER_PSR_SET/CLEAR, don't forget cpl!)// - set shared_mem isr: isr.ei to instr following HYPER_SSM_I// and isr.ri to cr.isr.ri (all other bits zero)// - cover and set shared_mem precover_ifs to cr.ifs// ^^^ MISSED THIS FOR fast_break??// - set shared_mem interrupt_delivery_enabled to 0// - set shared_mem interrupt_collection_enabled to 0// - set r31 to SHAREDINFO_ADDR// - virtual bank switch 0// maybe implement later// - verify that there really IS a deliverable interrupt pending// - set shared_mem iva// needs to be done but not implemented (in reflect_interruption)// - set shared_mem iipa// don't know for sure// - set shared_mem unat// r16 == cr.isr// r17 == cr.iim// r18 == XSI_PSR_IC// r19 == ipsr.cpl // r31 == prENTRY(hyper_ssm_i)#ifndef FAST_SSM_I br.spnt.few dispatch_break_fault ;;#endif // give up for now if: ipsr.be==1, ipsr.pp==1 mov r30=cr.ipsr mov r29=cr.iip;; extr.u r21=r30,IA64_PSR_PP_BIT,1 ;; cmp.ne p7,p0=r21,r0(p7) br.sptk.many dispatch_break_fault ;;#ifdef FAST_HYPERPRIVOP_CNT movl r20=FAST_HYPERPRIVOP_PERFC(HYPERPRIVOP_SSM_I);; ld4 r21=[r20];; adds r21=1,r21;; st4 [r20]=r21;;#endif // set shared_mem iip to instruction after HYPER_SSM_I extr.u r20=r30,IA64_PSR_RI_BIT,2 ;; cmp.eq p6,p7=2,r20 ;;(p6) mov r20=0(p6) adds r29=16,r29(p7) adds r20=1,r20 ;; dep r30=r20,r30,IA64_PSR_RI_BIT,2 // adjust cr.ipsr.ri but don't save yet adds r21=XSI_IIP_OFS-XSI_PSR_IC_OFS,r18 ;; st8 [r21]=r29 ;; // set shared_mem isr extr.u r16=r16,IA64_ISR_IR_BIT,1;; // grab cr.isr.ir bit dep r16=r16,r0,IA64_ISR_IR_BIT,1;; // insert into cr.isr (rest of bits zero) dep r16=r20,r16,IA64_PSR_RI_BIT,2 // deposit cr.isr.ri adds r21=XSI_ISR_OFS-XSI_PSR_IC_OFS,r18 ;; st8 [r21]=r16 // set cr.ipsr mov r29=r30 movl r28=DELIVER_PSR_SET movl r27=~(DELIVER_PSR_CLR & (~IA64_PSR_CPL));; and r29=r29,r27;; or r29=r29,r28;; // set hpsr_dfh to ipsr adds r28=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; ld1 r28=[r28];; dep r29=r28,r29,IA64_PSR_DFH_BIT,1;; mov cr.ipsr=r29;; // set shared_mem ipsr (from ipsr in r30 with ipsr.ri already set) extr.u r29=r30,IA64_PSR_CPL0_BIT,2;; cmp.eq p7,p0=CONFIG_CPL0_EMUL,r29;;(p7) dep r30=0,r30,IA64_PSR_CPL0_BIT,2 // FOR SSM_I ONLY, also turn on psr.i and psr.ic movl r28=(IA64_PSR_DT|IA64_PSR_IT|IA64_PSR_RT|IA64_PSR_I|IA64_PSR_IC)// movl r27=~(IA64_PSR_BE|IA64_PSR_PP|IA64_PSR_BN);; movl r27=~IA64_PSR_BN;; or r30=r30,r28;; and r30=r30,r27;; mov r20=1 movl r22=THIS_CPU(current_psr_i_addr) adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;; ld8 r22=[r22] adds r27=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; ld1 r28=[r27];; st1 [r27]=r0 dep r30=r28,r30,IA64_PSR_DFH_BIT,1 ;; st8 [r21]=r30;; // set shared_mem interrupt_delivery_enabled to 0 // set shared_mem interrupt_collection_enabled to 0 st1 [r22]=r20 st4 [r18]=r0 // cover and set shared_mem precover_ifs to cr.ifs // set shared_mem ifs to 0 cover ;; mov r20=cr.ifs adds r21=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; st8 [r21]=r0 ;; adds r21=XSI_PRECOVER_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; st8 [r21]=r20 ;; // leave cr.ifs alone for later rfi // set iip to go to event callback handler movl r22=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;; ld8 r22=[r22];; adds r22=IA64_VCPU_EVENT_CALLBACK_IP_OFFSET,r22;; ld8 r24=[r22];; mov cr.iip=r24;; // OK, now all set to go except for switch to virtual bank0 mov r30=r2 mov r29=r3 ;; adds r2=XSI_BANK1_R16_OFS-XSI_PSR_IC_OFS,r18 adds r3=(XSI_BANK1_R16_OFS+8)-XSI_PSR_IC_OFS,r18 // temporarily save ar.unat mov r28=ar.unat bsw.1;; // FIXME?: ar.unat is not really handled correctly, // but may not matter if the OS is NaT-clean .mem.offset 0,0; st8.spill [r2]=r16,16 .mem.offset 8,0; st8.spill [r3]=r17,16 ;; .mem.offset 0,0; st8.spill [r2]=r18,16 .mem.offset 8,0; st8.spill [r3]=r19,16 ;; .mem.offset 0,0; st8.spill [r2]=r20,16 .mem.offset 8,0; st8.spill [r3]=r21,16 ;; .mem.offset 0,0; st8.spill [r2]=r22,16 .mem.offset 8,0; st8.spill [r3]=r23,16 ;; .mem.offset 0,0; st8.spill [r2]=r24,16 .mem.offset 8,0; st8.spill [r3]=r25,16 ;; .mem.offset 0,0; st8.spill [r2]=r26,16 .mem.offset 8,0; st8.spill [r3]=r27,16 ;; .mem.offset 0,0; st8.spill [r2]=r28,16 .mem.offset 8,0; st8.spill [r3]=r29,16 ;; .mem.offset 0,0; st8.spill [r2]=r30,16 .mem.offset 8,0; st8.spill [r3]=r31,16 ;; bsw.0 ;; mov r27=ar.unat adds r26=XSI_B1NATS_OFS-XSI_PSR_IC_OFS,r18 ;; //save bank1 ar.unat st8 [r26]=r27 //restore ar.unat mov ar.unat=r28 mov r2=r30 mov r3=r29 adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; st4 [r20]=r0 mov pr=r31,-1 ;; rfi ;;END(hyper_ssm_i)// reflect domain clock interrupt// r31 == pr// r30 == cr.ivr// r29 == rpGLOBAL_ENTRY(fast_tick_reflect)#ifndef FAST_TICK // see beginning of file br.cond.sptk.many rp;;#endif mov r28=IA64_TIMER_VECTOR;; cmp.ne p6,p0=r28,r30(p6) br.cond.spnt.few rp;; movl r20=THIS_CPU(cpu_info)+IA64_CPUINFO_ITM_NEXT_OFFSET;; ld8 r26=[r20] mov r27=ar.itc;; adds r27=200,r27;; // safety margin cmp.ltu p6,p0=r26,r27(p6) br.cond.spnt.few rp;; mov r17=cr.ipsr;; // slow path if: ipsr.pp==1 extr.u r21=r17,IA64_PSR_PP_BIT,1 ;; cmp.ne p6,p0=r21,r0(p6) br.cond.spnt.few rp;; // definitely have a domain tick mov cr.eoi=r0 mov rp=r29 mov cr.itm=r26 // ensure next tick#ifdef FAST_REFLECT_CNT movl r20=PERFC(fast_reflect + (0x3000>>8));; ld4 r21=[r20];; adds r21=1,r21;; st4 [r20]=r21;;#endif // vcpu_pend_timer(current) movl r18=THIS_CPU(current_psr_ic_addr) ;; ld8 r18=[r18] ;; adds r20=XSI_ITV_OFS-XSI_PSR_IC_OFS,r18 ;; ld8 r20=[r20];; cmp.eq p6,p0=r20,r0 // if cr.itv==0 done(p6) br.cond.spnt.few fast_tick_reflect_done;; tbit.nz p6,p0=r20,16;; // check itv.m (discard) bit(p6) br.cond.spnt.few fast_tick_reflect_done;; extr.u r27=r20,0,6 // r27 has low 6 bits of itv.vector extr.u r26=r20,6,2 // r26 has irr index of itv.vector movl r19=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;; ld8 r19=[r19];; adds r22=IA64_VCPU_DOMAIN_ITM_LAST_OFFSET,r19 adds r23=IA64_VCPU_DOMAIN_ITM_OFFSET,r19;; ld8 r24=[r22] ld8 r23=[r23];; cmp.eq p6,p0=r23,r24 // skip if this tick already delivered(p6) br.cond.spnt.few fast_tick_reflect_done;; // set irr bit adds r21=IA64_VCPU_IRR0_OFFSET,r19 shl r26=r26,3;; add r21=r21,r26 mov r25=1;; shl r22=r25,r27 ld8 r23=[r21];; or r22=r22,r23;; st8 [r21]=r22 // set evtchn_upcall_pending! adds r20=XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS,r18;; ld8 r20=[r20];; adds r20=-1,r20;; // evtchn_upcall_pending st1 [r20]=r25 // if interrupted at pl0, we're done extr.u r16=r17,IA64_PSR_CPL0_BIT,2;; cmp.eq p6,p0=r16,r0;;(p6) br.cond.spnt.few fast_tick_reflect_done;; // if guest vpsr.i is off, we're done movl r21=THIS_CPU(current_psr_i_addr);; ld8 r21=[r21];; ld1 r21=[r21];; cmp.eq p0,p6=r21,r0(p6) br.cond.spnt.few fast_tick_reflect_done;; // OK, we have a clock tick to deliver to the active domain! // so deliver to iva+0x3000 // r17 == cr.ipsr // r18 == XSI_PSR_IC // r19 == IA64_KR(CURRENT) // r31 == pr mov r16=cr.isr mov r29=cr.iip adds r21=XSI_IIP_OFS-XSI_PSR_IC_OFS,r18 ;; st8 [r21]=r29 // set shared_mem isr extr.u r16=r16,IA64_ISR_IR_BIT,1;; // grab cr.isr.ir bit dep r16=r16,r0,IA64_ISR_IR_BIT,1 // insert into cr.isr (rest of bits zero) extr.u r20=r17,IA64_PSR_RI_BIT,2;; // get ipsr.ri dep r16=r20,r16,IA64_PSR_RI_BIT,2 // deposit cr.isr.ei adds r21=XSI_ISR_OFS-XSI_PSR_IC_OFS,r18;; st8 [r21]=r16 // set cr.ipsr (make sure cpl==2!) mov r29=r17 movl r28=DELIVER_PSR_SET | (CONFIG_CPL0_EMUL << IA64_PSR_CPL0_BIT) movl r27=~DELIVER_PSR_CLR;; and r29=r29,r27;; or r29=r29,r28;; mov cr.ipsr=r29;; // set shared_mem ipsr (from ipsr in r17 with ipsr.ri already set) extr.u r29=r17,IA64_PSR_CPL0_BIT,2;; cmp.eq p7,p0=CONFIG_CPL0_EMUL,r29;;(p7) dep r17=0,r17,IA64_PSR_CPL0_BIT,2 movl r28=(IA64_PSR_DT|IA64_PSR_IT|IA64_PSR_RT) movl r27=~(IA64_PSR_PP|IA64_PSR_BN|IA64_PSR_I|IA64_PSR_IC);; or r17=r17,r28;; and r17=r17,r27 ld4 r16=[r18];; cmp.ne p6,p0=r16,r0 movl r22=THIS_CPU(current_psr_i_addr);; ld8 r22=[r22](p6) dep r17=-1,r17,IA64_PSR_IC_BIT,1 ;; ld1 r16=[r22];; cmp.eq p6,p0=r16,r0;;(p6) dep r17=-1,r17,IA64_PSR_I_BIT,1 mov r20=1 adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18;; st8 [r21]=r17 // set shared_mem interrupt_delivery_enabled to 0 // set shared_mem interrupt_collection_enabled to 0 st1 [r22]=r20 st4 [r18]=r0;; // cover and set shared_mem precover_ifs to cr.ifs // set shared_mem ifs to 0 cover ;; mov r20=cr.ifs adds r21=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; st8 [r21]=r0 ;; adds r21=XSI_PRECOVER_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; st8 [r21]=r20 // leave cr.ifs alone for later rfi // set iip to go to domain IVA break instruction vector adds r22=IA64_VCPU_IVA_OFFSET,r19;; ld8 r23=[r22] movl r24=0x3000;; add r24=r24,r23;; mov cr.iip=r24 // OK, now all set to go except for switch to virtual bank0 mov r30=r2 mov r29=r3#ifdef HANDLE_AR_UNAT mov r28=ar.unat#endif ;; adds r2=XSI_BANK1_R16_OFS-XSI_PSR_IC_OFS,r18 adds r3=(XSI_BANK1_R16_OFS+8)-XSI_PSR_IC_OFS,r18 ;; bsw.1;; .mem.offset 0,0; st8.spill [r2]=r16,16 .mem.offset 8,0; st8.spill [r3]=r17,16 ;; .mem.offset 0,0; st8.spill [r2]=r18,16 .mem.offset 8,0; st8.spill [r3]=r19,16 ;; .mem.offset 0,0; st8.spill [r2]=r20,16 .mem.offset 8,0; st8.spill [r3]=r21,16 ;; .mem.offset 0,0; st8.spill [r2]=r22,16 .mem.offset 8,0; st8.spill [r3]=r23,16 ;; .mem.offset 0,0; st8.spill [r2]=r24,16 .mem.offset 8,0; st8.spill [r3]=r25,16 ;; .mem.offset 0,0; st8.spill [r2]=r26,16 .mem.offset 8,0; st8.spill [r3]=r27,16 ;; .mem.offset 0,0; st8.spill [r2]=r28,16 .mem.offset 8,0; st8.spill [r3]=r29,16 ;; .mem.offset 0,0; st8.spill [r2]=r30,16 .mem.offset 8,0; st8.spill [r3]=r31,16 ;;#ifdef HANDLE_AR_UNAT // r16~r23 are preserved regsin bank0 regs, we need to restore them, // r24~r31 are scratch regs, we don't need to handle NaT bit, // because OS handler must assign it before access it ld8 r16=[r2],16 ld8 r17=[r3],16;; ld8 r18=[r2],16 ld8 r19=[r3],16;; ld8 r20=[r2],16 ld8 r21=[r3],16;; ld8 r22=[r2],16 ld8 r23=[r3],16;;#endif ;; bsw.0 ;; mov r24=ar.unat mov r2=r30 mov r3=r29#ifdef HANDLE_AR_UNAT mov ar.unat=r28#endif ;; adds r25=XSI_B1NATS_OFS-XSI_PSR_IC_OFS,r18 adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; st8 [r25]=r24 st4 [r20]=r0fast_tick_reflect_done: mov pr=r31,-1 ;; rfiEND(fast_tick_reflect)// reflect domain breaks directly to domain// r16 == cr.isr// r17 == cr.iim// r18 == XSI_PSR_IC// r19 == ipsr.cpl// r31 == prGLOBAL_ENTRY(fast_break_reflect)#ifndef FAST_BREAK // see beginning of file br.sptk.many dispatch_break_fault ;;#endif mov r30=cr.ipsr mov r29=cr.iip;; extr.u r21=r30,IA64_PSR_PP_BIT,1 ;; cmp.ne p7,p0=r21,r0(p7) br.spnt.few dispatch_break_fault ;; movl r20=IA64_PSR_CPL ;; and r22=r20,r30 ;; cmp.ne p7,p0=r22,r0(p7) br.spnt.many 1f ;; cmp.eq p7,p0=r17,r0(p7) br.spnt.few dispatch_break_fault ;;#ifdef CRASH_DEBUG movl r21=CDB_BREAK_NUM ;; cmp.eq p7,p0=r17,r21(p7) br.spnt.few dispatch_break_fault ;;#endif 1: #if 1 /* special handling in case running on simulator */ movl r20=first_break;; ld4 r23=[r20] movl r21=0x80001 movl r22=0x80002;; cmp.ne p7,p0=r23,r0(p7) br.spnt.few dispatch_break_fault ;; cmp.eq p7,p0=r21,r17(p7) br.spnt.few dispatch_break_fault ;; cmp.eq p7,p0=r22,r17(p7) br.spnt.few dispatch_break_fault ;;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -