On 16/01/15 10:09, Paul Durrant wrote:
> HVM guests have always been confined to using the domain callback
> via (see HVM_PARAM_CALLBACK_IRQ) to receive event notifications.
> This is usually an IOAPIC vector and is only used if the event
> channel is bound to vcpu 0.
>
> PVHVM Linux uses a pre-defined interrupt vector for the event
> channel upcall, set using HVM_PARAM_CALLBACK_IRQ by ORing in a
> special bit (bit 57) into the value (see params.h). However, it
> does not assert the interrupt via the emulated local APIC.
>
> This mechanism is not suitable in the general case since Windows
> (and potentially other OSes) because they:
>
> - cannot guarantee the same vector for all VCPUs
> - do require the upcall to be asserted via the local APIC
>
> This patch adds a new HVM op allowing a guest to specify a local
> APIC vector to use as an upcall notification for a specific vcpu
> therefore coping with the case of differing vector numbers.
>
> Signed-off-by: Paul Durrant <paul.durr...@citrix.com>
> Cc: Keir Fraser <k...@xen.org>
> Cc: Jan Beulich <jbeul...@suse.com>
> Cc: David Vrabel <david.vra...@citrix.com>
> ---
> v2:
>  - Addressed comments from Andrew Cooper
>    - Check vector >=16
>    - Put hypercall in x86-specific section
>
> v3:
>  - Addressed comments from Jan Beulich
>    - More verbose check-in comment
>
> v4:
>  - Amended check-in comment as suggested by David Vrabel
>
> v5:
>  - Addressed comments from Jan Beulich
>
>  xen/arch/x86/hvm/hvm.c          |   30 ++++++++++++++++++++++++++++++
>  xen/arch/x86/hvm/irq.c          |    8 +++++++-
>  xen/include/asm-x86/hvm/vcpu.h  |    1 +
>  xen/include/public/hvm/hvm_op.h |   19 +++++++++++++++++++
>  4 files changed, 57 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 8b06bfd..85e43b8 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -5514,6 +5514,31 @@ static int hvmop_destroy_ioreq_server(
>      return rc;
>  }
>  
> +static int hvmop_set_evtchn_upcall_vector(
> +    XEN_GUEST_HANDLE_PARAM(xen_hvm_set_evtchn_upcall_vector_t) uop)
> +{
> +    xen_hvm_set_evtchn_upcall_vector_t op;
> +    struct domain *d = current->domain;
> +    struct vcpu *v;
> +
> +    if ( copy_from_guest(&op, uop, 1) )
> +        return -EFAULT;
> +
> +    if ( !is_hvm_domain(d) )
> +        return -EINVAL;
> +
> +    if ( op.vector < 0x10 )
> +        return -EINVAL;
> +
> +    if ( op.vcpu >= d->max_vcpus || (v = d->vcpu[op.vcpu]) == NULL )
> +        return -ENOENT;
> +
> +    printk(XENLOG_G_INFO "%pv: upcall vector %u\n", v, op.vector);
> +
> +    v->arch.hvm_vcpu.evtchn_upcall_vector = op.vector;
> +    return 0;
> +}
> +
>  /*
>   * Note that this value is effectively part of the ABI, even if we don't need
>   * to make it a formal part of it: A guest suspended for migration in the
> @@ -5573,6 +5598,11 @@ long do_hvm_op(unsigned long op, 
> XEN_GUEST_HANDLE_PARAM(void) arg)
>              guest_handle_cast(arg, xen_hvm_destroy_ioreq_server_t));
>          break;
>      
> +    case HVMOP_set_evtchn_upcall_vector:
> +        rc = hvmop_set_evtchn_upcall_vector(
> +            guest_handle_cast(arg, xen_hvm_set_evtchn_upcall_vector_t));
> +        break;
> +    
>      case HVMOP_set_param:
>      case HVMOP_get_param:
>      {
> diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
> index 35f4f94..743429e 100644
> --- a/xen/arch/x86/hvm/irq.c
> +++ b/xen/arch/x86/hvm/irq.c
> @@ -218,7 +218,13 @@ void hvm_assert_evtchn_irq(struct vcpu *v)
>          return;
>      }
>  
> -    if ( is_hvm_pv_evtchn_vcpu(v) )
> +    if ( v->arch.hvm_vcpu.evtchn_upcall_vector != 0 )
> +    {
> +        uint8_t vector = v->arch.hvm_vcpu.evtchn_upcall_vector;
> +
> +        vlapic_set_irq(vcpu_vlapic(v), vector, 0);
> +    }
> +    else if ( is_hvm_pv_evtchn_vcpu(v) )
>          vcpu_kick(v);
>      else if ( v->vcpu_id == 0 )
>          hvm_set_callback_irq_level(v);
> diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
> index 01e0665..edd4523 100644
> --- a/xen/include/asm-x86/hvm/vcpu.h
> +++ b/xen/include/asm-x86/hvm/vcpu.h
> @@ -160,6 +160,7 @@ struct hvm_vcpu {
>      } u;
>  
>      struct tasklet      assert_evtchn_irq_tasklet;
> +    u8                  evtchn_upcall_vector;
>  
>      struct nestedvcpu   nvcpu;
>  
> diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
> index a4e5345..a857561 100644
> --- a/xen/include/public/hvm/hvm_op.h
> +++ b/xen/include/public/hvm/hvm_op.h
> @@ -370,6 +370,25 @@ 
> DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
>  
>  #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
>  
> +#if defined(__i386__) || defined(__x86_64__)
> +
> +/*
> + * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for 
> event
> + *                                 channel upcalls on the specified <vcpu>. 
> If set,
> + *                                 this vector will be used in preference to 
> the
> + *                                 domain global callback via (see
> + *                                 HVM_PARAM_CALLBACK_IRQ).
> + */
> +#define HVMOP_set_evtchn_upcall_vector 23
> +struct xen_hvm_set_evtchn_upcall_vector {
> +    uint32_t vcpu;
> +    uint8_t vector;
> +};
> +typedef struct xen_hvm_set_evtchn_upcall_vector 
> xen_hvm_set_evtchn_upcall_vector_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_evtchn_upcall_vector_t);

I think you should remove "set" from the structure name.  Who knows -
someone might want to implement a get hypercall in the future.

Other than that, Reviewed-by: Andrew Cooper <andrew.coop...@citrix.com>

> +
> +#endif /* defined(__i386__) || defined(__x86_64__) */
> +
>  #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
>  
>  /*


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

Reply via email to