|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH V4] x86/vm_event: Added support for VM_EVENT_REASON_INTERRUPT
On 11/11/2016 05:48 PM, Razvan Cojocaru wrote:
> Added support for a new event type, VM_EVENT_REASON_INTERRUPT,
> which is now fired in a one-shot manner when enabled via the new
> VM_EVENT_FLAG_GET_NEXT_INTERRUPT vm_event response flag.
> The patch also fixes the behaviour of the xc_hvm_inject_trap()
> hypercall, which would lead to non-architectural interrupts
> overwriting pending (specifically reinjected) architectural ones.
>
> Signed-off-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>
> Acked-by: Tamas K Lengyel <tamas@xxxxxxxxxxxxx>
>
> ---
> Changes since V3:
> - Const-ified struct vmcb_struct *vmcb in svm_get_pending_event().
> - Made next_interrupt_enabled into a bool.
> ---
> xen/arch/x86/hvm/hvm.c | 22 +++++++++++++++++++++-
> xen/arch/x86/hvm/monitor.c | 14 ++++++++++++++
> xen/arch/x86/hvm/svm/svm.c | 15 +++++++++++++++
> xen/arch/x86/hvm/vmx/vmx.c | 20 ++++++++++++++++++++
> xen/arch/x86/vm_event.c | 5 +++++
> xen/common/vm_event.c | 3 +++
> xen/include/asm-arm/vm_event.h | 6 ++++++
> xen/include/asm-x86/domain.h | 4 ++++
> xen/include/asm-x86/hvm/hvm.h | 1 +
> xen/include/asm-x86/hvm/monitor.h | 2 ++
> xen/include/asm-x86/monitor.h | 3 ++-
> xen/include/public/domctl.h | 1 +
> xen/include/public/vm_event.h | 18 ++++++++++++++++++
> xen/include/xen/vm_event.h | 2 ++
> 14 files changed, 114 insertions(+), 2 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 704fd64..93af5b8 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -469,6 +469,12 @@ void hvm_migrate_pirqs(struct vcpu *v)
> spin_unlock(&d->event_lock);
> }
>
> +static bool hvm_get_pending_event(struct vcpu *v, struct hvm_trap *info)
> +{
> + info->cr2 = v->arch.hvm_vcpu.guest_cr[2];
> + return hvm_funcs.get_pending_event(v, info);
> +}
> +
> void hvm_do_resume(struct vcpu *v)
> {
> check_wakeup_from_wait();
> @@ -535,9 +541,23 @@ void hvm_do_resume(struct vcpu *v)
> /* Inject pending hw/sw trap */
> if ( v->arch.hvm_vcpu.inject_trap.vector != -1 )
> {
> - hvm_inject_trap(&v->arch.hvm_vcpu.inject_trap);
> + if ( !hvm_event_pending(v) )
> + hvm_inject_trap(&v->arch.hvm_vcpu.inject_trap);
> +
> v->arch.hvm_vcpu.inject_trap.vector = -1;
> }
> +
> + if ( unlikely(v->arch.vm_event) &&
> v->arch.monitor.next_interrupt_enabled )
> + {
> + struct hvm_trap info;
> +
> + if ( hvm_get_pending_event(v, &info) )
> + {
> + hvm_monitor_interrupt(info.vector, info.type, info.error_code,
> + info.cr2);
> + v->arch.monitor.next_interrupt_enabled = false;
> + }
> + }
> }
>
> static int hvm_print_line(
> diff --git a/xen/arch/x86/hvm/monitor.c b/xen/arch/x86/hvm/monitor.c
> index 401a8c6..69a88ad 100644
> --- a/xen/arch/x86/hvm/monitor.c
> +++ b/xen/arch/x86/hvm/monitor.c
> @@ -150,6 +150,20 @@ int hvm_monitor_cpuid(unsigned long insn_length,
> unsigned int leaf,
> return monitor_traps(curr, 1, &req);
> }
>
> +void hvm_monitor_interrupt(unsigned int vector, unsigned int type,
> + unsigned int err, uint64_t cr2)
> +{
> + vm_event_request_t req = {
> + .reason = VM_EVENT_REASON_INTERRUPT,
> + .u.interrupt.x86.vector = vector,
> + .u.interrupt.x86.type = type,
> + .u.interrupt.x86.error_code = err,
> + .u.interrupt.x86.cr2 = cr2,
> + };
> +
> + monitor_traps(current, 1, &req);
> +}
> +
> /*
> * Local variables:
> * mode: C
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index c9dbbea..7fe27e4 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -2222,6 +2222,20 @@ static void svm_invlpg(struct vcpu *v, unsigned long
> vaddr)
> svm_asid_g_invlpg(v, vaddr);
> }
>
> +static bool svm_get_pending_event(struct vcpu *v, struct hvm_trap *info)
> +{
> + const struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
> +
> + if ( vmcb->eventinj.fields.v )
> + return false;
> +
> + info->vector = vmcb->eventinj.fields.vector;
> + info->type = vmcb->eventinj.fields.type;
> + info->error_code = vmcb->eventinj.fields.errorcode;
> +
> + return true;
> +}
> +
> static struct hvm_function_table __initdata svm_function_table = {
> .name = "SVM",
> .cpu_up_prepare = svm_cpu_up_prepare,
> @@ -2252,6 +2266,7 @@ static struct hvm_function_table __initdata
> svm_function_table = {
> .inject_trap = svm_inject_trap,
> .init_hypercall_page = svm_init_hypercall_page,
> .event_pending = svm_event_pending,
> + .get_pending_event = svm_get_pending_event,
> .invlpg = svm_invlpg,
> .cpuid_intercept = svm_cpuid_intercept,
> .wbinvd_intercept = svm_wbinvd_intercept,
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index 9a8f694..961a20b 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -2134,6 +2134,25 @@ static int vmx_set_mode(struct vcpu *v, int mode)
> return 0;
> }
>
> +static bool vmx_get_pending_event(struct vcpu *v, struct hvm_trap *info)
> +{
> + unsigned long intr_info, error_code;
> +
> + vmx_vmcs_enter(v);
> + __vmread(VM_ENTRY_INTR_INFO, &intr_info);
> + __vmread(VM_ENTRY_EXCEPTION_ERROR_CODE, &error_code);
> + vmx_vmcs_exit(v);
> +
> + if ( !(intr_info & INTR_INFO_VALID_MASK) )
> + return false;
> +
> + info->vector = MASK_EXTR(intr_info, INTR_INFO_VECTOR_MASK);
> + info->type = MASK_EXTR(intr_info, INTR_INFO_INTR_TYPE_MASK);
> + info->error_code = error_code;
> +
> + return true;
> +}
> +
> static struct hvm_function_table __initdata vmx_function_table = {
> .name = "VMX",
> .cpu_up_prepare = vmx_cpu_up_prepare,
> @@ -2163,6 +2182,7 @@ static struct hvm_function_table __initdata
> vmx_function_table = {
> .inject_trap = vmx_inject_trap,
> .init_hypercall_page = vmx_init_hypercall_page,
> .event_pending = vmx_event_pending,
> + .get_pending_event = vmx_get_pending_event,
> .invlpg = vmx_invlpg,
> .cpu_up = vmx_cpu_up,
> .cpu_down = vmx_cpu_down,
> diff --git a/xen/arch/x86/vm_event.c b/xen/arch/x86/vm_event.c
> index 1e88d67..c26e9f0 100644
> --- a/xen/arch/x86/vm_event.c
> +++ b/xen/arch/x86/vm_event.c
> @@ -134,6 +134,11 @@ void vm_event_set_registers(struct vcpu *v,
> vm_event_response_t *rsp)
> v->arch.user_regs.eip = rsp->data.regs.x86.rip;
> }
>
> +void vm_event_monitor_next_interrupt(struct vcpu *v)
> +{
> + v->arch.monitor.next_interrupt_enabled = false;
Apologies, this should of course be true. I'm sorry for the typo. Will
send V5.
Thanks,
Razvan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |