📄 vcpu.c
字号:
}#endif vector = vcpu_check_pending_interrupts(vcpu); if (vector == SPURIOUS_VECTOR) { PSCB(vcpu, pending_interruption) = 0; *pval = vector; return IA64_NO_FAULT; }#ifdef HEARTBEAT_FREQ if (domid >= N_DOMS) domid = N_DOMS - 1;#if 0 if (vector == (PSCB(vcpu, itv) & 0xff)) { if (!(++count[domid] & ((HEARTBEAT_FREQ * 1024) - 1))) { printk("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n", domid, count[domid], nonclockcount[domid]); //count[domid] = 0; //dump_runq(); } }#endif else nonclockcount[domid]++;#endif // now have an unmasked, pending, deliverable vector! // getting ivr has "side effects"#ifdef IRQ_DEBUG if (firsttime[vector]) { printk("*** First get_ivr on vector=%lu,itc=%lx\n", vector, ia64_get_itc()); firsttime[vector] = 0; }#endif /* if delivering a timer interrupt, remember domain_itm, which * needs to be done before clearing irr */ if (vector == (PSCB(vcpu, itv) & 0xff)) { PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm); } i = vector >> 6; mask = 1L << (vector & 0x3f);//printk("ZZZZZZ vcpu_get_ivr: setting insvc mask for vector %lu\n",vector); PSCBX(vcpu, insvc[i]) |= mask; PSCBX(vcpu, irr[i]) &= ~mask; //PSCB(vcpu,pending_interruption)--; *pval = vector; return IA64_NO_FAULT;}IA64FAULT vcpu_get_tpr(VCPU * vcpu, u64 * pval){ *pval = PSCB(vcpu, tpr); return IA64_NO_FAULT;}IA64FAULT vcpu_get_eoi(VCPU * vcpu, u64 * pval){ *pval = 0L; // reads of eoi always return 0 return IA64_NO_FAULT;}IA64FAULT vcpu_get_irr0(VCPU * vcpu, u64 * pval){ *pval = PSCBX(vcpu, irr[0]); return IA64_NO_FAULT;}IA64FAULT vcpu_get_irr1(VCPU * vcpu, u64 * pval){ *pval = PSCBX(vcpu, irr[1]); return IA64_NO_FAULT;}IA64FAULT vcpu_get_irr2(VCPU * vcpu, u64 * pval){ *pval = PSCBX(vcpu, irr[2]); return IA64_NO_FAULT;}IA64FAULT vcpu_get_irr3(VCPU * vcpu, u64 * pval){ *pval = PSCBX(vcpu, irr[3]); return IA64_NO_FAULT;}IA64FAULT vcpu_get_itv(VCPU * vcpu, u64 * pval){ *pval = PSCB(vcpu, itv); return IA64_NO_FAULT;}IA64FAULT vcpu_get_pmv(VCPU * vcpu, u64 * pval){ *pval = PSCB(vcpu, pmv); return IA64_NO_FAULT;}IA64FAULT vcpu_get_cmcv(VCPU * vcpu, u64 * pval){ *pval = PSCB(vcpu, cmcv); return IA64_NO_FAULT;}IA64FAULT vcpu_get_lrr0(VCPU * vcpu, u64 * pval){ // fix this when setting values other than m-bit is supported gdprintk(XENLOG_DEBUG, "vcpu_get_lrr0: Unmasked interrupts unsupported\n"); *pval = (1L << 16); return IA64_NO_FAULT;}IA64FAULT vcpu_get_lrr1(VCPU * vcpu, u64 * pval){ // fix this when setting values other than m-bit is supported gdprintk(XENLOG_DEBUG, "vcpu_get_lrr1: Unmasked interrupts unsupported\n"); *pval = (1L << 16); return IA64_NO_FAULT;}IA64FAULT vcpu_set_lid(VCPU * vcpu, u64 val){ printk("vcpu_set_lid: Setting cr.lid is unsupported\n"); return IA64_ILLOP_FAULT;}IA64FAULT vcpu_set_tpr(VCPU * vcpu, u64 val){ if (val & 0xff00) return IA64_RSVDREG_FAULT; PSCB(vcpu, tpr) = val; /* This can unmask interrupts. */ if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR) PSCB(vcpu, pending_interruption) = 1; return IA64_NO_FAULT;}IA64FAULT vcpu_set_eoi(VCPU * vcpu, u64 val){ u64 *p, bits, vec, bitnum; int i; p = &PSCBX(vcpu, insvc[3]); for (i = 3; (i >= 0) && !(bits = *p); i--, p--) ; if (i < 0) { printk("Trying to EOI interrupt when none are in-service.\n"); return IA64_NO_FAULT; } bitnum = ia64_fls(bits); vec = bitnum + (i * 64); /* clear the correct bit */ bits &= ~(1L << bitnum); *p = bits; /* clearing an eoi bit may unmask another pending interrupt... */ if (!vcpu->vcpu_info->evtchn_upcall_mask) { // but only if enabled... // worry about this later... Linux only calls eoi // with interrupts disabled printk("Trying to EOI interrupt with interrupts enabled\n"); } if (vcpu_check_pending_interrupts(vcpu) != SPURIOUS_VECTOR) PSCB(vcpu, pending_interruption) = 1;//printk("YYYYY vcpu_set_eoi: Successful\n"); return IA64_NO_FAULT;}IA64FAULT vcpu_set_lrr0(VCPU * vcpu, u64 val){ if (!(val & (1L << 16))) { printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n"); return IA64_ILLOP_FAULT; } // no place to save this state but nothing to do anyway return IA64_NO_FAULT;}IA64FAULT vcpu_set_lrr1(VCPU * vcpu, u64 val){ if (!(val & (1L << 16))) { printk("vcpu_set_lrr0: Unmasked interrupts unsupported\n"); return IA64_ILLOP_FAULT; } // no place to save this state but nothing to do anyway return IA64_NO_FAULT;}IA64FAULT vcpu_set_itv(VCPU * vcpu, u64 val){ /* Check reserved fields. */ if (val & 0xef00) return IA64_ILLOP_FAULT; PSCB(vcpu, itv) = val; if (val & 0x10000) { /* Disable itm. */ PSCBX(vcpu, domain_itm) = 0; } else vcpu_set_next_timer(vcpu); return IA64_NO_FAULT;}IA64FAULT vcpu_set_pmv(VCPU * vcpu, u64 val){ if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT; PSCB(vcpu, pmv) = val; return IA64_NO_FAULT;}IA64FAULT vcpu_set_cmcv(VCPU * vcpu, u64 val){ if (val & 0xef00) /* reserved fields */ return IA64_RSVDREG_FAULT; PSCB(vcpu, cmcv) = val; return IA64_NO_FAULT;}/************************************************************************** VCPU temporary register access routines**************************************************************************/u64 vcpu_get_tmp(VCPU * vcpu, u64 index){ if (index > 7) return 0; return PSCB(vcpu, tmp[index]);}void vcpu_set_tmp(VCPU * vcpu, u64 index, u64 val){ if (index <= 7) PSCB(vcpu, tmp[index]) = val;}/**************************************************************************Interval timer routines**************************************************************************/BOOLEAN vcpu_timer_disabled(VCPU * vcpu){ u64 itv = PSCB(vcpu, itv); return (!itv || !!(itv & 0x10000));}BOOLEAN vcpu_timer_inservice(VCPU * vcpu){ u64 itv = PSCB(vcpu, itv); return test_bit(itv, PSCBX(vcpu, insvc));}BOOLEAN vcpu_timer_expired(VCPU * vcpu){ unsigned long domain_itm = PSCBX(vcpu, domain_itm); unsigned long now = ia64_get_itc(); if (!domain_itm) return FALSE; if (now < domain_itm) return FALSE; if (vcpu_timer_disabled(vcpu)) return FALSE; return TRUE;}void vcpu_safe_set_itm(unsigned long val){ unsigned long epsilon = 100; unsigned long flags; u64 now = ia64_get_itc(); local_irq_save(flags); while (1) {//printk("*** vcpu_safe_set_itm: Setting itm to %lx, itc=%lx\n",val,now); ia64_set_itm(val); if (val > (now = ia64_get_itc())) break; val = now + epsilon; epsilon <<= 1; } local_irq_restore(flags);}void vcpu_set_next_timer(VCPU * vcpu){ u64 d = PSCBX(vcpu, domain_itm); //u64 s = PSCBX(vcpu,xen_itm); u64 s = local_cpu_data->itm_next; u64 now = ia64_get_itc(); /* gloss over the wraparound problem for now... we know it exists * but it doesn't matter right now */ if (is_idle_domain(vcpu->domain)) {// printk("****** vcpu_set_next_timer called during idle!!\n"); vcpu_safe_set_itm(s); return; } //s = PSCBX(vcpu,xen_itm); if (d && (d > now) && (d < s)) { vcpu_safe_set_itm(d); //using_domain_as_itm++; } else { vcpu_safe_set_itm(s); //using_xen_as_itm++; }}IA64FAULT vcpu_set_itm(VCPU * vcpu, u64 val){ //UINT now = ia64_get_itc(); //if (val < now) val = now + 1000;//printk("*** vcpu_set_itm: called with %lx\n",val); PSCBX(vcpu, domain_itm) = val; vcpu_set_next_timer(vcpu); return IA64_NO_FAULT;}IA64FAULT vcpu_set_itc(VCPU * vcpu, u64 val){#define DISALLOW_SETTING_ITC_FOR_NOW#ifdef DISALLOW_SETTING_ITC_FOR_NOW static int did_print; if (!did_print) { printk("vcpu_set_itc: Setting ar.itc is currently disabled " "(this message is only displayed once)\n"); did_print = 1; }#else u64 oldnow = ia64_get_itc(); u64 olditm = PSCBX(vcpu, domain_itm); unsigned long d = olditm - oldnow; unsigned long x = local_cpu_data->itm_next - oldnow; u64 newnow = val, min_delta; local_irq_disable(); if (olditm) { printk("**** vcpu_set_itc(%lx): vitm changed to %lx\n", val, newnow + d); PSCBX(vcpu, domain_itm) = newnow + d; } local_cpu_data->itm_next = newnow + x; d = PSCBX(vcpu, domain_itm); x = local_cpu_data->itm_next; ia64_set_itc(newnow); if (d && (d > newnow) && (d < x)) { vcpu_safe_set_itm(d); //using_domain_as_itm++; } else { vcpu_safe_set_itm(x); //using_xen_as_itm++; } local_irq_enable();#endif return IA64_NO_FAULT;}IA64FAULT vcpu_get_itm(VCPU * vcpu, u64 * pval){ //FIXME: Implement this printk("vcpu_get_itm: Getting cr.itm is unsupported... continuing\n"); return IA64_NO_FAULT; //return IA64_ILLOP_FAULT;}IA64FAULT vcpu_get_itc(VCPU * vcpu, u64 * pval){ //TODO: Implement this printk("vcpu_get_itc: Getting ar.itc is unsupported\n"); return IA64_ILLOP_FAULT;}void vcpu_pend_timer(VCPU * vcpu){ u64 itv = PSCB(vcpu, itv) & 0xff; if (vcpu_timer_disabled(vcpu)) return; //if (vcpu_timer_inservice(vcpu)) return; if (PSCBX(vcpu, domain_itm_last) == PSCBX(vcpu, domain_itm)) { // already delivered an interrupt for this so // don't deliver another return; } if (vcpu->arch.event_callback_ip) { /* A small window may occur when injecting vIRQ while related * handler has not been registered. Don't fire in such case. */ if (vcpu->virq_to_evtchn[VIRQ_ITC]) { send_guest_vcpu_virq(vcpu, VIRQ_ITC); PSCBX(vcpu, domain_itm_last) = PSCBX(vcpu, domain_itm); } } else vcpu_pend_interrupt(vcpu, itv);}// returns true if ready to deliver a timer interrupt too earlyu64 vcpu_timer_pending_early(VCPU * vcpu){ u64 now = ia64_get_itc(); u64 itm = PSCBX(vcpu, domain_itm); if (vcpu_timer_disabled(vcpu)) return 0; if (!itm) return 0; return (vcpu_deliverable_timer(vcpu) && (now < itm));}/**************************************************************************Privileged operation emulation routines**************************************************************************/static void vcpu_force_tlb_miss(VCPU * vcpu, u64 ifa){ PSCB(vcpu, ifa) = ifa; PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa); vcpu_thash(current, ifa, &PSCB(current, iha));}IA64FAULT vcpu_force_inst_miss(VCPU * vcpu, u64 ifa){ vcpu_force_tlb_miss(vcpu, ifa); return vcpu_get_rr_ve(vcpu, ifa) ? IA64_INST_TLB_VECTOR : IA64_ALT_INST_TLB_VECTOR;}IA64FAULT vcpu_force_data_miss(VCPU * vcpu, u64 ifa){ vcpu_force_tlb_miss(vcpu, ifa); return vcpu_get_rr_ve(vcpu, ifa) ? IA64_DATA_TLB_VECTOR : IA64_ALT_DATA_TLB_VECTOR;}IA64FAULT vcpu_rfi(VCPU * vcpu){ u64 ifs; REGS *regs = vcpu_regs(vcpu); vcpu_set_psr(vcpu, PSCB(vcpu, ipsr)); ifs = PSCB(vcpu, ifs); if (ifs & 0x8000000000000000UL) regs->cr_ifs = ifs; regs->cr_iip = PSCB(vcpu, iip); return IA64_NO_FAULT;}IA64FAULT vcpu_cover(VCPU * vcpu){ // TODO: Only allowed for current vcpu REGS *regs = vcpu_regs(vcpu); if (!PSCB(vcpu, interrupt_collection_enabled)) { PSCB(vcpu, ifs) = regs->cr_ifs; } regs->cr_ifs = 0; return IA64_NO_FAULT;}IA64FAULT vcpu_thash(VCPU * vcpu, u64 vadr, u64 * pval){ u64 pta = PSCB(vcpu, pta); u64 pta_sz = (pta & IA64_PTA_SZ(0x3f)) >> IA64_PTA_SZ_BIT; u64 pta_base = pta & ~((1UL << IA64_PTA_BASE_BIT) - 1); u64 Mask = (1L << pta_sz) - 1; u64 Mask_60_15 = (Mask >> 15) & 0x3fffffffffff; u64 compMask_60_15 = ~Mask_60_15; u64 rr_ps = vcpu_get_rr_ps(vcpu, vadr); u64 VHPT_offset = (vadr >> rr_ps) << 3; u64 VHPT_addr1 = vadr & 0xe000000000000000L; u64 VHPT_addr2a = ((pta_base >> 15) & 0x3fffffffffff) & compMask_60_15; u64 VHPT_addr2b = ((VHPT_offset >> 15) & 0x3fffffffffff) & Mask_60_15; u64 VHPT_addr3 = VHPT_offset & 0x7fff; u64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) | VHPT_addr3;//verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr); *pval = VHPT_addr; return IA64_NO_FAULT;}IA64FAULT vcpu_ttag(VCPU * vcpu, u64 vadr, u64 * padr){ printk("vcpu_ttag: ttag instruction unsupported\n"); return IA64_ILLOP_FAULT;}int warn_region0_address = 0; // FIXME later: tie to a boot parameter?/* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */static inline int range_overlap(u64 b1, u64 e1, u64 b2, u64 e2){ return (b1 <= e2) && (e1 >= b2);}/* Crash domain if [base, base + page_size] and Xen virtual space overlaps. Note: LSBs of base inside page_size are ignored. */static inline voidcheck_xen_space_overlap(const char *func, u64 base, u64 page_size){ /* Overlaps can occur only in region 7.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -