From 827fffedda015e11cece82a7927f7cc5b3486de9 Mon Sep 17 00:00:00 2001 From: Binbin Wu Date: Wed, 23 Jan 2019 07:12:49 +0000 Subject: [PATCH] hv: exception: fault type exception should set resume flag in rflags According to SDM 17.3.1.1, for any fault-class exception except a debug exception generated in response to an instruction breakpoint, the value pushed for RF is 1. This patch set Resume Flag for fault class exceptions. Tracked-On: #2405 Signed-off-by: Binbin Wu Acked-by: Anthony Xu Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/virq.c | 32 +++++++++++++++++++++++++++++++ hypervisor/include/arch/x86/irq.h | 1 + 2 files changed, 33 insertions(+) diff --git a/hypervisor/arch/x86/guest/virq.c b/hypervisor/arch/x86/guest/virq.c index 70b037dde..3e4a916c8 100644 --- a/hypervisor/arch/x86/guest/virq.c +++ b/hypervisor/arch/x86/guest/virq.c @@ -14,6 +14,12 @@ #define EXCEPTION_CLASS_CONT 2 #define EXCEPTION_CLASS_PF 3 +/* Exception types */ +#define EXCEPTION_FAULT 0U +#define EXCEPTION_TRAP 1U +#define EXCEPTION_ABORT 2U +#define EXCEPTION_INTERRUPT 3U + static const uint16_t exception_type[32] = { [0] = VMX_INT_TYPE_HW_EXP, [1] = VMX_INT_TYPE_HW_EXP, @@ -49,6 +55,24 @@ static const uint16_t exception_type[32] = { [31] = VMX_INT_TYPE_HW_EXP }; +static uint8_t get_exception_type(uint32_t vector) +{ + uint8_t type; + + /* Treat #DB as trap until decide to support Debug Registers */ + if ((vector > 31U) || (vector == IDT_NMI)) { + type = EXCEPTION_INTERRUPT; + } else if ((vector == IDT_DB) || (vector == IDT_BP) || (vector == IDT_OF)) { + type = EXCEPTION_TRAP; + } else if ((vector == IDT_DF) || (vector == IDT_MC)) { + type = EXCEPTION_ABORT; + } else { + type = EXCEPTION_FAULT; + } + + return type; +} + static bool is_guest_irq_enabled(struct acrn_vcpu *vcpu) { uint64_t guest_rflags, guest_state; @@ -254,6 +278,14 @@ static void vcpu_inject_exception(struct acrn_vcpu *vcpu, uint32_t vector) /* retain rip for exception injection */ vcpu_retain_rip(vcpu); + + /* SDM 17.3.1.1 For any fault-class exception except a debug exception generated in response to an + * instruction breakpoint, the value pushed for RF is 1. + * #DB is treated as Trap in get_exception_type, so RF will not be set for instruction breakpoint. + */ + if (get_exception_type(vector) == EXCEPTION_FAULT) { + vcpu_set_rflags(vcpu, vcpu_get_rflags(vcpu) | HV_ARCH_VCPU_RFLAGS_RF); + } } static int32_t vcpu_inject_hi_exception(struct acrn_vcpu *vcpu) diff --git a/hypervisor/include/arch/x86/irq.h b/hypervisor/include/arch/x86/irq.h index bd3126b8e..6e633ae6a 100644 --- a/hypervisor/include/arch/x86/irq.h +++ b/hypervisor/include/arch/x86/irq.h @@ -107,6 +107,7 @@ uint32_t irq_to_vector(uint32_t irq); /* RFLAGS */ #define HV_ARCH_VCPU_RFLAGS_IF (1UL<<9U) +#define HV_ARCH_VCPU_RFLAGS_RF (1UL<<16U) /* Interruptability State info */ #define HV_ARCH_VCPU_BLOCKED_BY_MOVSS (1UL<<1U)