|
35 | 35 |
|
36 | 36 | #define ACRN_DBG_INTR 6
|
37 | 37 |
|
| 38 | +#define EXCEPTION_CLASS_BENIGN 1 |
| 39 | +#define EXCEPTION_CLASS_CONT 2 |
| 40 | +#define EXCEPTION_CLASS_PF 3 |
| 41 | + |
38 | 42 | static const uint16_t exception_type[] = {
|
39 | 43 | [0] = VMX_INT_TYPE_HW_EXP,
|
40 | 44 | [1] = VMX_INT_TYPE_HW_EXP,
|
@@ -229,6 +233,59 @@ void dump_lapic(void)
|
229 | 233 | mmio_read_long(HPA2HVA(LAPIC_BASE + LAPIC_INT_REQUEST_REGISTER_7)));
|
230 | 234 | }
|
231 | 235 |
|
| 236 | +/* SDM Vol3 -6.15, Table 6-4 - interrupt and exception classes */ |
| 237 | +static int get_excep_class(int32_t vector) |
| 238 | +{ |
| 239 | + if (vector == IDT_DE || vector == IDT_TS || vector == IDT_NP || |
| 240 | + vector == IDT_SS || vector == IDT_GP) |
| 241 | + return EXCEPTION_CLASS_CONT; |
| 242 | + else if (vector == IDT_PF || vector == IDT_VE) |
| 243 | + return EXCEPTION_CLASS_PF; |
| 244 | + else |
| 245 | + return EXCEPTION_CLASS_BENIGN; |
| 246 | +} |
| 247 | + |
| 248 | +int vcpu_queue_exception(struct vcpu *vcpu, int32_t vector, |
| 249 | + uint32_t err_code) |
| 250 | +{ |
| 251 | + if (vector >= 32) { |
| 252 | + pr_err("invalid exception vector %d", vector); |
| 253 | + return -EINVAL; |
| 254 | + } |
| 255 | + |
| 256 | + if (vcpu->arch_vcpu.exception_info.exception >= 0) { |
| 257 | + int32_t prev_vector = |
| 258 | + vcpu->arch_vcpu.exception_info.exception; |
| 259 | + int32_t new_class, prev_class; |
| 260 | + |
| 261 | + /* SDM vol3 - 6.15, Table 6-5 - conditions for generating a |
| 262 | + * double fault */ |
| 263 | + prev_class = get_excep_class(prev_vector); |
| 264 | + new_class = get_excep_class(vector); |
| 265 | + if (prev_vector == IDT_DF && |
| 266 | + new_class != EXCEPTION_CLASS_BENIGN) { |
| 267 | + /* triple fault happen - shutdwon mode */ |
| 268 | + return vcpu_make_request(vcpu, ACRN_REQUEST_TRP_FAULT); |
| 269 | + } else if ((prev_class == EXCEPTION_CLASS_CONT && |
| 270 | + new_class == EXCEPTION_CLASS_CONT) || |
| 271 | + (prev_class == EXCEPTION_CLASS_PF && |
| 272 | + new_class != EXCEPTION_CLASS_BENIGN)) { |
| 273 | + /* generate double fault */ |
| 274 | + vector = IDT_DF; |
| 275 | + err_code = 0; |
| 276 | + } |
| 277 | + } |
| 278 | + |
| 279 | + vcpu->arch_vcpu.exception_info.exception = vector; |
| 280 | + |
| 281 | + if (exception_type[vector] & EXCEPTION_ERROR_CODE_VALID) |
| 282 | + vcpu->arch_vcpu.exception_info.error = err_code; |
| 283 | + else |
| 284 | + vcpu->arch_vcpu.exception_info.error = 0; |
| 285 | + |
| 286 | + return 0; |
| 287 | +} |
| 288 | + |
232 | 289 | int vcpu_inject_extint(struct vcpu *vcpu)
|
233 | 290 | {
|
234 | 291 | return vcpu_make_request(vcpu, ACRN_REQUEST_EXTINT);
|
|
0 commit comments