static void collect_interruption(VCPU *vcpu) { u64 ipsr; u64 vdcr; u64 vifs; IA64_PSR vpsr; REGS * regs = vcpu_regs(vcpu); vpsr.val = vmx_vcpu_get_psr(vcpu); vcpu_bsw0(vcpu); if(vpsr.ic){ /* Sync mpsr id/da/dd/ss/ed bits to vipsr * since after guest do rfi, we still want these bits on in * mpsr */ ipsr = regs->cr_ipsr; vpsr.val = vpsr.val | (ipsr & (IA64_PSR_ID | IA64_PSR_DA | IA64_PSR_DD |IA64_PSR_SS |IA64_PSR_ED)); vcpu_set_ipsr(vcpu, vpsr.val); /* Currently, for trap, we do not advance IIP to next * instruction. That's because we assume caller already * set up IIP correctly */ vcpu_set_iip(vcpu , regs->cr_iip); /* set vifs.v to zero */ vifs = VCPU(vcpu,ifs); vifs &= ~IA64_IFS_V; vcpu_set_ifs(vcpu, vifs); vcpu_set_iipa(vcpu, VMX(vcpu,cr_iipa)); } vdcr = VCPU(vcpu,dcr); /* Set guest psr * up/mfl/mfh/pk/dt/rt/mc/it keeps unchanged * be: set to the value of dcr.be * pp: set to the value of dcr.pp */ vpsr.val &= INITIAL_PSR_VALUE_AT_INTERRUPTION; vpsr.val |= ( vdcr & IA64_DCR_BE); /* VDCR pp bit position is different from VPSR pp bit */ if ( vdcr & IA64_DCR_PP ) { vpsr.val |= IA64_PSR_PP; } else { vpsr.val &= ~IA64_PSR_PP;; } vmx_vcpu_set_psr(vcpu, vpsr.val); }
IA64FAULT vmx_vcpu_rfi(VCPU *vcpu) { // TODO: Only allowed for current vcpu u64 ifs, psr; REGS *regs = vcpu_regs(vcpu); psr = VCPU(vcpu,ipsr); if (psr & IA64_PSR_BN) vcpu_bsw1(vcpu); else vcpu_bsw0(vcpu); vmx_vcpu_set_psr(vcpu,psr); vmx_ia64_set_dcr(vcpu); ifs=VCPU(vcpu,ifs); if(ifs>>63) regs->cr_ifs = ifs; regs->cr_iip = VCPU(vcpu,iip); return (IA64_NO_FAULT); }