exception: add vcpu_queue_exception function

add func vcpu_queue_exception to queue exception based on SDM Vol3 Table 6-5,
which may cause #DF or triple fault

Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com>
Acked-by: Tian, Kevin <kevin.tian@intel.com>
This commit is contained in:
Jason Chen CJ 2018-05-28 13:04:48 +08:00 committed by lijinxia
parent 44af2690f6
commit 277830aba8
3 changed files with 59 additions and 0 deletions

View File

@ -35,6 +35,10 @@
#define ACRN_DBG_INTR 6
#define EXCEPTION_CLASS_BENIGN 1
#define EXCEPTION_CLASS_CONT 2
#define EXCEPTION_CLASS_PF 3
static const uint16_t exception_type[] = {
[0] = VMX_INT_TYPE_HW_EXP,
[1] = VMX_INT_TYPE_HW_EXP,
@ -229,6 +233,59 @@ void dump_lapic(void)
mmio_read_long(HPA2HVA(LAPIC_BASE + LAPIC_INT_REQUEST_REGISTER_7)));
}
/* SDM Vol3 -6.15, Table 6-4 - interrupt and exception classes */
static int get_excep_class(int32_t vector)
{
if (vector == IDT_DE || vector == IDT_TS || vector == IDT_NP ||
vector == IDT_SS || vector == IDT_GP)
return EXCEPTION_CLASS_CONT;
else if (vector == IDT_PF || vector == IDT_VE)
return EXCEPTION_CLASS_PF;
else
return EXCEPTION_CLASS_BENIGN;
}
int vcpu_queue_exception(struct vcpu *vcpu, int32_t vector,
uint32_t err_code)
{
if (vector >= 32) {
pr_err("invalid exception vector %d", vector);
return -EINVAL;
}
if (vcpu->arch_vcpu.exception_info.exception >= 0) {
int32_t prev_vector =
vcpu->arch_vcpu.exception_info.exception;
int32_t new_class, prev_class;
/* SDM vol3 - 6.15, Table 6-5 - conditions for generating a
* double fault */
prev_class = get_excep_class(prev_vector);
new_class = get_excep_class(vector);
if (prev_vector == IDT_DF &&
new_class != EXCEPTION_CLASS_BENIGN) {
/* triple fault happen - shutdwon mode */
return vcpu_make_request(vcpu, ACRN_REQUEST_TRP_FAULT);
} else if ((prev_class == EXCEPTION_CLASS_CONT &&
new_class == EXCEPTION_CLASS_CONT) ||
(prev_class == EXCEPTION_CLASS_PF &&
new_class != EXCEPTION_CLASS_BENIGN)) {
/* generate double fault */
vector = IDT_DF;
err_code = 0;
}
}
vcpu->arch_vcpu.exception_info.exception = vector;
if (exception_type[vector] & EXCEPTION_ERROR_CODE_VALID)
vcpu->arch_vcpu.exception_info.error = err_code;
else
vcpu->arch_vcpu.exception_info.error = 0;
return 0;
}
int vcpu_inject_extint(struct vcpu *vcpu)
{
return vcpu_make_request(vcpu, ACRN_REQUEST_EXTINT);

View File

@ -109,6 +109,7 @@
#define IDT_AC 17 /* #AC: Alignment Check */
#define IDT_MC 18 /* #MC: Machine Check */
#define IDT_XF 19 /* #XF: SIMD Floating-Point Exception */
#define IDT_VE 20 /* #VE: Virtualization Exception */
/*Bits in EFER special registers */
#define EFER_LMA 0x000000400 /* Long mode active (R) */

View File

@ -185,6 +185,7 @@ int vcpu_inject_extint(struct vcpu *vcpu);
int vcpu_inject_nmi(struct vcpu *vcpu);
int vcpu_inject_gp(struct vcpu *vcpu);
int vcpu_make_request(struct vcpu *vcpu, int eventid);
int vcpu_queue_exception(struct vcpu *vcpu, int32_t vector, uint32_t err_code);
int exception_vmexit_handler(struct vcpu *vcpu);
int interrupt_window_vmexit_handler(struct vcpu *vcpu);