int kvm_xen_set_evtchn_fast(struct kvm_kernel_irq_routing_entry *e,
			    struct kvm *kvm)
{
	struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
	struct kvm_vcpu *vcpu;
	unsigned long *pending_bits, *mask_bits;
	unsigned long flags;
	int port_word_bit;
	bool kick_vcpu = false;
	int idx;
	int rc;

	vcpu = kvm_get_vcpu_by_id(kvm, e->xen_evtchn.vcpu);
	if (!vcpu)
		return -1;

	if (!vcpu->arch.xen.vcpu_info_set)
		return -1;

	if (e->xen_evtchn.port >= max_evtchn_port(kvm))
		return -1;

	rc = -EWOULDBLOCK;
	read_lock_irqsave(&gpc->lock, flags);

	idx = srcu_read_lock(&kvm->srcu);
	if (!kvm_gfn_to_pfn_cache_check(kvm, gpc, gpc->gpa, PAGE_SIZE))
		goto out_rcu;

	if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode) {
		struct shared_info *shinfo = gpc->khva;
		pending_bits = (unsigned long *)&shinfo->evtchn_pending;
		mask_bits = (unsigned long *)&shinfo->evtchn_mask;
		port_word_bit = e->xen_evtchn.port / 64;
	} else {
		struct compat_shared_info *shinfo = gpc->khva;
		pending_bits = (unsigned long *)&shinfo->evtchn_pending;
		mask_bits = (unsigned long *)&shinfo->evtchn_mask;
		port_word_bit = e->xen_evtchn.port / 32;
	}

	/*
	 * If this port wasn't already set, and if it isn't masked, then
	 * we try to set the corresponding bit in the in-kernel shadow of
	 * evtchn_pending_sel for the target vCPU. And if *that* wasn't
	 * already set, then we kick the vCPU in question to write to the
	 * *real* evtchn_pending_sel in its own guest vcpu_info struct.
	 */
	if (test_and_set_bit(e->xen_evtchn.port, pending_bits)) {
		rc = 0; /* It was already raised */
	} else if (test_bit(e->xen_evtchn.port, mask_bits)) {
		rc = -1; /* Masked */
	} else {
		rc = 1; /* Delivered. But was the vCPU waking already? */
		if (!test_and_set_bit(port_word_bit, &vcpu->arch.xen.evtchn_pending_sel))
			kick_vcpu = true;
	}

 out_rcu:
	srcu_read_unlock(&kvm->srcu, idx);
	read_unlock_irqrestore(&gpc->lock, flags);

	if (kick_vcpu) {
		kvm_make_request(KVM_REQ_EVENT, vcpu);
		kvm_vcpu_kick(vcpu);
	}

	return rc;
}
int kvm_xen_set_evtchn_fast(struct kvm_kernel_irq_routing_entry *e,
			    struct kvm *kvm)
{
	struct gfn_to_pfn_cache *gpc = &kvm->arch.xen.shinfo_cache;
	struct kvm_vcpu *vcpu;
	unsigned long *pending_bits, *mask_bits;
	unsigned long flags;
	int port_word_bit;
	bool kick_vcpu = false;
	int idx;
	int rc;

	vcpu = kvm_get_vcpu_by_id(kvm, e->xen_evtchn.vcpu);
	if (!vcpu)
		return -1;

	if (!vcpu->arch.xen.vcpu_info_set)
		return -1;

	if (e->xen_evtchn.port >= max_evtchn_port(kvm))
		return -1;

	rc = -EWOULDBLOCK;
	read_lock_irqsave(&gpc->lock, flags);

	idx = srcu_read_lock(&kvm->srcu);
	if (!kvm_gfn_to_pfn_cache_check(kvm, gpc, gpc->gpa, PAGE_SIZE))
		goto out_rcu;

	if (IS_ENABLED(CONFIG_64BIT) && kvm->arch.xen.long_mode) {
		struct shared_info *shinfo = gpc->khva;
		pending_bits = (unsigned long *)&shinfo->evtchn_pending;
		mask_bits = (unsigned long *)&shinfo->evtchn_mask;
		port_word_bit = e->xen_evtchn.port / 64;
	} else {
		struct compat_shared_info *shinfo = gpc->khva;
		pending_bits = (unsigned long *)&shinfo->evtchn_pending;
		mask_bits = (unsigned long *)&shinfo->evtchn_mask;
		port_word_bit = e->xen_evtchn.port / 32;
	}

	 
	if (test_and_set_bit(e->xen_evtchn.port, pending_bits)) {
		rc = 0;  
	} else if (test_bit(e->xen_evtchn.port, mask_bits)) {
		rc = -1;  
	} else {
		rc = 1;  
		if (!test_and_set_bit(port_word_bit, &vcpu->arch.xen.evtchn_pending_sel))
			kick_vcpu = true;
	}

 out_rcu:
	srcu_read_unlock(&kvm->srcu, idx);
	read_unlock_irqrestore(&gpc->lock, flags);

	if (kick_vcpu) {
		kvm_make_request(KVM_REQ_EVENT, vcpu);
		kvm_vcpu_kick(vcpu);
	}

	return rc;
}