int kvm_pending_timer(struct kvm_vcpu *vcpu)
{ return test_bit(INT_TI, &vcpu->arch.irq_pending);
}
/* * Only support illegal instruction or illegal Address Error exception, * Other exceptions are injected by hardware in kvm mode
*/ staticvoid _kvm_deliver_exception(struct kvm_vcpu *vcpu, unsignedint code, unsignedint subcode)
{ unsignedlong val, vec_size;
/* * BADV is added for EXCCODE_ADE exception * Use PC register (GVA address) if it is instruction exeception * Else use BADV from host side (GPA address) for data exeception
*/ if (code == EXCCODE_ADE) { if (subcode == EXSUBCODE_ADEF)
val = vcpu->arch.pc; else
val = vcpu->arch.badv;
kvm_write_hw_gcsr(LOONGARCH_CSR_BADV, val);
}
/* Set exception instruction */
kvm_write_hw_gcsr(LOONGARCH_CSR_BADI, vcpu->arch.badi);
/* * Save CRMD in PRMD * Set IRQ disabled and PLV0 with CRMD
*/
val = kvm_read_hw_gcsr(LOONGARCH_CSR_CRMD);
kvm_write_hw_gcsr(LOONGARCH_CSR_PRMD, val);
val = val & ~(CSR_CRMD_PLV | CSR_CRMD_IE);
kvm_write_hw_gcsr(LOONGARCH_CSR_CRMD, val);
/* Set exception PC address */
kvm_write_hw_gcsr(LOONGARCH_CSR_ERA, vcpu->arch.pc);
/* * Set exception code * Exception and interrupt can be inject at the same time * Hardware will handle exception first and then extern interrupt * Exception code is Ecode in ESTAT[16:21] * Interrupt code in ESTAT[0:12]
*/
val = kvm_read_hw_gcsr(LOONGARCH_CSR_ESTAT);
val = (val & ~CSR_ESTAT_EXC) | code;
kvm_write_hw_gcsr(LOONGARCH_CSR_ESTAT, val);
/* Calculate expcetion entry address */
val = kvm_read_hw_gcsr(LOONGARCH_CSR_ECFG);
vec_size = (val & CSR_ECFG_VS) >> CSR_ECFG_VS_SHIFT; if (vec_size)
vec_size = (1 << vec_size) * 4;
val = kvm_read_hw_gcsr(LOONGARCH_CSR_EENTRY);
vcpu->arch.pc = val + code * vec_size;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.