Re: [PATCH v8 2/2] kvm: x86: hyperv: guest->host event signaling via eventfd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2018-01-31 16:56+0300, Roman Kagan:
> In Hyper-V, the fast guest->host notification mechanism is the
> SIGNAL_EVENT hypercall, with a single parameter of the connection ID to
> signal.
> 
> Currently this hypercall incurs a user exit and requires the userspace
> to decode the parameters and trigger the notification of the potentially
> different I/O context.
> 
> To avoid the costly user exit, process this hypercall and signal the
> corresponding eventfd in KVM, similar to ioeventfd.  The association
> between the connection id and the eventfd is established via the newly
> introduced KVM_HYPERV_EVENTFD ioctl, and maintained in an
> (srcu-protected) IDR.
> 
> Signed-off-by: Roman Kagan <rkagan@xxxxxxxxxxxxx>
> Reviewed-by: David Hildenbrand <david@xxxxxxxxxx>
> ---
> v7 -> v8:
>  - rebase to latest master (adjust ioctl and doc section numbers)
> 
> v6 -> v7:
>  - reject non-zero flag number as invalid
>  - adjust error returns to better match the spec
>  [these changes didn't look critical so I retained David's r-b]
> 
> v5 -> v6:
>  - drop unnecessary srcu_read_lock/unlock, and clean up after that
> 
> v4 -> v5:
>  - fix block comment formatting
> 
> v3 -> v4:
>  - switch to kvm_vcpu_read_guest and take srcu_read_lock around it
>  - rework and document the interpretation of the hypercall parameter
>  - merge !fast version into kvm_hvcall_signal_event for brevity
> 
> v2 -> v3:
>  - expand docs on allowed values and return codes
>  - fix uninitialized return
>  - style fixes
> 
> v1 -> v2:
>  - make data types consistent
>  - get by without the recently dropped struct hv_input_signal_event
>  - fix subject prefix
> 
>  Documentation/virtual/kvm/api.txt  |  31 +++++++++++
>  arch/x86/include/asm/kvm_host.h    |   2 +
>  arch/x86/include/uapi/asm/hyperv.h |   2 +
>  arch/x86/kvm/hyperv.h              |   1 +
>  include/uapi/linux/kvm.h           |  13 +++++
>  arch/x86/kvm/hyperv.c              | 103 ++++++++++++++++++++++++++++++++++++-
>  arch/x86/kvm/x86.c                 |  10 ++++
>  7 files changed, 161 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
> @@ -1226,6 +1227,43 @@ static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu)
>  	return 1;
>  }
>  
> +static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param)
> +{
> +	struct eventfd_ctx *eventfd;
> +
> +	if (unlikely(!fast)) {
> +		int ret;
> +		gpa_t gpa = param;
> +
> +		if ((gpa & (__alignof__(param) - 1)) ||
> +		    offset_in_page(gpa) + sizeof(param) > PAGE_SIZE)
> +			return HV_STATUS_INVALID_ALIGNMENT;
> +
> +		ret = kvm_vcpu_read_guest(vcpu, gpa, &param, sizeof(param));
> +		if (ret < 0)
> +			return HV_STATUS_INVALID_ALIGNMENT;
> +	}

I have completely missed this series in the past, sorry.

It looks good, but I don't follow this:

> +
> +	/*
> +	 * Per spec, bits 32-47 contain the extra "flag number".  However, we
> +	 * have no use for it, and in all known usecases it is zero, so just
> +	 * require it here.
> +	 */

The spec says:

  FlagNumber specifies the relative index of the event flag that the
  caller wants to set within the target SIEF area. This number is
  relative to the base flag number associated with the port.

And then:

  11.5.1 Event Flag Delivery
  When a partition calls HvSignalEvent, it specifies an event flag
  number. The hypervisor responds by atomically setting a bit within the
  receiving virtual processor’s SIEF page. (See section 11.9 for a
  detailed description of the SIEF page.) Virtual processors whose SynIC
  or SIEF page is disabled will not be considered as potential targets.
  If no targets are available, the hypervisor terminates the operation
  and returns an error to the caller.

  If the event flag was previously cleared, the hypervisor attempts to
  notify the receiving partition that the flag is now set by generating
  an edge-triggered interrupt. The target virtual processor, along with
  the target SINTx, is specified as part of a port’s creation. (See the
  following for information about ports.) If the SINTx is masked,
  HvSignalEvent returns HV_STATUS_INVALID_SYNIC_STATE.

  As with any fixed-priority external interrupt, the interrupt is not
  acknowledged by the virtual processor until the process priority
  register (PPR) is less than the vector specified in the SINTx register
  and interrupts are not masked by the virtual processor (rFLAGS[IF] is
  set to 1).

Don't we want to pass the flag into userspace?

Thanks.

> +	if (param & 0xffff00000000)
> +		return HV_STATUS_INVALID_PARAMETER;
> +	/* remaining bits are reserved-zero */
> +	if (param & ~KVM_HYPERV_CONN_ID_MASK)
> +		return HV_STATUS_INVALID_HYPERCALL_INPUT;
> +
> +	/* conn_to_evt is protected by vcpu->kvm->srcu */
> +	eventfd = idr_find(&vcpu->kvm->arch.hyperv.conn_to_evt, param);
> +	if (!eventfd)
> +		return HV_STATUS_INVALID_PORT_ID;
> +
> +	eventfd_signal(eventfd, 1);
> +	return HV_STATUS_SUCCESS;
> +}
> +



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux