All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: "Radim Krčmář" <rkrcmar@redhat.com>,
	linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: "Lan, Tianyu" <tianyu.lan@intel.com>,
	Igor Mammedov <imammedo@redhat.com>,
	Jan Kiszka <jan.kiszka@web.de>, Peter Xu <peterx@redhat.com>
Subject: Re: [PATCH v1 02/11] KVM: x86: add kvm_apic_map_get_dest_lapic
Date: Fri, 1 Jul 2016 09:57:25 +0200	[thread overview]
Message-ID: <7f5a8277-f905-e6a2-fba8-7f859d300b66@redhat.com> (raw)
In-Reply-To: <20160630205429.16480-3-rkrcmar@redhat.com>



On 30/06/2016 22:54, Radim Krčmář wrote:
> kvm_irq_delivery_to_apic_fast and kvm_intr_is_single_vcpu_fast both
> compute the interrupt destination.  Factor the code.
> 
> 'struct kvm_lapic **dst = NULL' had to be added to silence GCC.
> GCC might complain about potential NULL access in the future, because it
> missed conditions that avoided uninitialized uses of dst.
> 
> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
> ---
>  v1: improved comment for kvm_apic_map_get_dest_lapic() [Peter]
> 
>  arch/x86/kvm/lapic.c | 241 ++++++++++++++++++++++-----------------------------
>  1 file changed, 103 insertions(+), 138 deletions(-)
> 
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index 22a6474af220..238b87b068db 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -671,14 +671,98 @@ static void kvm_apic_disabled_lapic_found(struct kvm *kvm)
>  	}
>  }
>  
> +/* Return true if the interrupt can be handled by using *bitmap as index mask
> + * for valid destinations in *dst array.
> + * Return false if kvm_apic_map_get_dest_lapic did nothing useful.
> + * Note: we may have zero kvm_lapic destinations when we return true, which
> + * means that the interrupt should be dropped.  In this case, *bitmap would be
> + * zero and *dst undefined.
> + */
> +static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm, struct kvm_lapic *src,
> +		struct kvm_lapic_irq *irq, struct kvm_apic_map *map,
> +		struct kvm_lapic ***dst, unsigned long *bitmap)
> +{
> +	int i, lowest;
> +	bool x2apic_ipi;
> +	u16 cid;
> +
> +	if (irq->shorthand == APIC_DEST_SELF) {
> +		*dst = &src;

This is not valid, &src dies as soon as you leave the function.  You
need to pass &src into kvm_apic_map_get_dest_lapic and here do something
like

	if (irq->shorthand) {
		if (irq->shorthand == APIC_DEST_SELF && p_src) {
			*dst = p_src;
			*bitmap = 1;
			return true;
		}
		return false;
	}

If it's not too hard, I'd like to have patch 4 before this one.

Paolo

> +		*bitmap = 1;
> +		return true;
> +	} else if (irq->shorthand)
> +		return false;
> +
> +	x2apic_ipi = src && apic_x2apic_mode(src);
> +	if (irq->dest_id == (x2apic_ipi ? X2APIC_BROADCAST : APIC_BROADCAST))
> +		return false;
> +
> +	if (!map)
> +		return false;
> +
> +	if (irq->dest_mode == APIC_DEST_PHYSICAL) {
> +		if (irq->dest_id >= ARRAY_SIZE(map->phys_map)) {
> +			*bitmap = 0;
> +		} else {
> +			*dst = &map->phys_map[irq->dest_id];
> +			*bitmap = 1;
> +		}
> +		return true;
> +	}
> +
> +	if (!kvm_apic_logical_map_valid(map))
> +		return false;
> +
> +	apic_logical_id(map, irq->dest_id, &cid, (u16 *)bitmap);
> +
> +	if (cid >= ARRAY_SIZE(map->logical_map)) {
> +		*bitmap = 0;
> +		return true;
> +	}
> +
> +	*dst = map->logical_map[cid];
> +
> +	if (!kvm_lowest_prio_delivery(irq))
> +		return true;
> +
> +	if (!kvm_vector_hashing_enabled()) {
> +		lowest = -1;
> +		for_each_set_bit(i, bitmap, 16) {
> +			if (!(*dst)[i])
> +				continue;
> +			if (lowest < 0)
> +				lowest = i;
> +			else if (kvm_apic_compare_prio((*dst)[i]->vcpu,
> +						(*dst)[lowest]->vcpu) < 0)
> +				lowest = i;
> +		}
> +	} else {
> +		if (!*bitmap)
> +			return true;
> +
> +		lowest = kvm_vector_to_index(irq->vector, hweight16(*bitmap),
> +				bitmap, 16);
> +
> +		if (!(*dst)[lowest]) {
> +			kvm_apic_disabled_lapic_found(kvm);
> +			*bitmap = 0;
> +			return true;
> +		}
> +	}
> +
> +	*bitmap = (lowest >= 0) ? 1 << lowest : 0;
> +
> +	return true;
> +}
> +
>  bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
>  		struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map)
>  {
>  	struct kvm_apic_map *map;
> -	unsigned long bitmap = 1;
> -	struct kvm_lapic **dst;
> +	unsigned long bitmap;
> +	struct kvm_lapic **dst = NULL;
>  	int i;
> -	bool ret, x2apic_ipi;
> +	bool ret;
>  
>  	*r = -1;
>  
> @@ -687,86 +771,19 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
>  		return true;
>  	}
>  
> -	if (irq->shorthand)
> -		return false;
> -
> -	x2apic_ipi = src && apic_x2apic_mode(src);
> -	if (irq->dest_id == (x2apic_ipi ? X2APIC_BROADCAST : APIC_BROADCAST))
> -		return false;
> -
> -	ret = true;
>  	rcu_read_lock();
>  	map = rcu_dereference(kvm->arch.apic_map);
>  
> -	if (!map) {
> -		ret = false;
> -		goto out;
> -	}
> -
> -	if (irq->dest_mode == APIC_DEST_PHYSICAL) {
> -		if (irq->dest_id >= ARRAY_SIZE(map->phys_map))
> -			goto out;
> -
> -		dst = &map->phys_map[irq->dest_id];
> -	} else {
> -		u16 cid;
> -
> -		if (!kvm_apic_logical_map_valid(map)) {
> -			ret = false;
> -			goto out;
> +	ret = kvm_apic_map_get_dest_lapic(kvm, src, irq, map, &dst, &bitmap);
> +	if (ret)
> +		for_each_set_bit(i, &bitmap, 16) {
> +			if (!dst[i])
> +				continue;
> +			if (*r < 0)
> +				*r = 0;
> +			*r += kvm_apic_set_irq(dst[i]->vcpu, irq, dest_map);
>  		}
>  
> -		apic_logical_id(map, irq->dest_id, &cid, (u16 *)&bitmap);
> -
> -		if (cid >= ARRAY_SIZE(map->logical_map))
> -			goto out;
> -
> -		dst = map->logical_map[cid];
> -
> -		if (!kvm_lowest_prio_delivery(irq))
> -			goto set_irq;
> -
> -		if (!kvm_vector_hashing_enabled()) {
> -			int l = -1;
> -			for_each_set_bit(i, &bitmap, 16) {
> -				if (!dst[i])
> -					continue;
> -				if (l < 0)
> -					l = i;
> -				else if (kvm_apic_compare_prio(dst[i]->vcpu,
> -							dst[l]->vcpu) < 0)
> -					l = i;
> -			}
> -			bitmap = (l >= 0) ? 1 << l : 0;
> -		} else {
> -			int idx;
> -			unsigned int dest_vcpus;
> -
> -			dest_vcpus = hweight16(bitmap);
> -			if (dest_vcpus == 0)
> -				goto out;
> -
> -			idx = kvm_vector_to_index(irq->vector,
> -				dest_vcpus, &bitmap, 16);
> -
> -			if (!dst[idx]) {
> -				kvm_apic_disabled_lapic_found(kvm);
> -				goto out;
> -			}
> -
> -			bitmap = (idx >= 0) ? 1 << idx : 0;
> -		}
> -	}
> -
> -set_irq:
> -	for_each_set_bit(i, &bitmap, 16) {
> -		if (!dst[i])
> -			continue;
> -		if (*r < 0)
> -			*r = 0;
> -		*r += kvm_apic_set_irq(dst[i]->vcpu, irq, dest_map);
> -	}
> -out:
>  	rcu_read_unlock();
>  	return ret;
>  }
> @@ -789,8 +806,9 @@ bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
>  			struct kvm_vcpu **dest_vcpu)
>  {
>  	struct kvm_apic_map *map;
> +	unsigned long bitmap;
> +	struct kvm_lapic **dst = NULL;
>  	bool ret = false;
> -	struct kvm_lapic *dst = NULL;
>  
>  	if (irq->shorthand)
>  		return false;
> @@ -798,69 +816,16 @@ bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
>  	rcu_read_lock();
>  	map = rcu_dereference(kvm->arch.apic_map);
>  
> -	if (!map)
> -		goto out;
> +	if (kvm_apic_map_get_dest_lapic(kvm, NULL, irq, map, &dst, &bitmap) &&
> +			hweight16(bitmap) == 1) {
> +		unsigned long i = find_first_bit(&bitmap, 16);
>  
> -	if (irq->dest_mode == APIC_DEST_PHYSICAL) {
> -		if (irq->dest_id == 0xFF)
> -			goto out;
> -
> -		if (irq->dest_id >= ARRAY_SIZE(map->phys_map))
> -			goto out;
> -
> -		dst = map->phys_map[irq->dest_id];
> -		if (dst && kvm_apic_present(dst->vcpu))
> -			*dest_vcpu = dst->vcpu;
> -		else
> -			goto out;
> -	} else {
> -		u16 cid;
> -		unsigned long bitmap = 1;
> -		int i, r = 0;
> -
> -		if (!kvm_apic_logical_map_valid(map))
> -			goto out;
> -
> -		apic_logical_id(map, irq->dest_id, &cid, (u16 *)&bitmap);
> -
> -		if (cid >= ARRAY_SIZE(map->logical_map))
> -			goto out;
> -
> -		if (kvm_vector_hashing_enabled() &&
> -				kvm_lowest_prio_delivery(irq)) {
> -			int idx;
> -			unsigned int dest_vcpus;
> -
> -			dest_vcpus = hweight16(bitmap);
> -			if (dest_vcpus == 0)
> -				goto out;
> -
> -			idx = kvm_vector_to_index(irq->vector, dest_vcpus,
> -						  &bitmap, 16);
> -
> -			dst = map->logical_map[cid][idx];
> -			if (!dst) {
> -				kvm_apic_disabled_lapic_found(kvm);
> -				goto out;
> -			}
> -
> -			*dest_vcpu = dst->vcpu;
> -		} else {
> -			for_each_set_bit(i, &bitmap, 16) {
> -				dst = map->logical_map[cid][i];
> -				if (++r == 2)
> -					goto out;
> -			}
> -
> -			if (dst && kvm_apic_present(dst->vcpu))
> -				*dest_vcpu = dst->vcpu;
> -			else
> -				goto out;
> +		if (dst[i]) {
> +			*dest_vcpu = dst[i]->vcpu;
> +			ret = true;
>  		}
>  	}
>  
> -	ret = true;
> -out:
>  	rcu_read_unlock();
>  	return ret;
>  }
> 

  reply	other threads:[~2016-07-01  7:58 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-30 20:54 [PATCH v1 00/11] KVM: x86: break the xAPIC barrier Radim Krčmář
2016-06-30 20:54 ` [PATCH v1 01/11] KVM: x86: bump KVM_SOFT_MAX_VCPUS to 240 Radim Krčmář
2016-07-01  8:42   ` Paolo Bonzini
2016-06-30 20:54 ` [PATCH v1 02/11] KVM: x86: add kvm_apic_map_get_dest_lapic Radim Krčmář
2016-07-01  7:57   ` Paolo Bonzini [this message]
2016-07-01 12:39     ` Radim Krčmář
2016-06-30 20:54 ` [PATCH v1 03/11] KVM: x86: dynamic kvm_apic_map Radim Krčmář
2016-06-30 22:15   ` Andrew Honig
2016-07-01  8:42     ` Paolo Bonzini
2016-07-01 12:44       ` Radim Krčmář
2016-07-01 14:03         ` Paolo Bonzini
2016-07-01 14:38           ` Radim Krčmář
2016-07-01 15:06             ` Paolo Bonzini
2016-07-01 15:12               ` Paolo Bonzini
2016-07-01 15:43                 ` Radim Krčmář
2016-07-01 16:38                   ` Paolo Bonzini
2016-07-01 15:35               ` Radim Krčmář
2016-07-01  7:33   ` Paolo Bonzini
2016-06-30 20:54 ` [PATCH v1 04/11] KVM: x86: use u16 for logical VCPU mask in lapic Radim Krčmář
2016-07-01  7:56   ` Paolo Bonzini
2016-07-01 12:48     ` Radim Krčmář
2016-07-01 14:04       ` Paolo Bonzini
2016-06-30 20:54 ` [PATCH v1 05/11] KVM: x86: use generic function for MSI parsing Radim Krčmář
2016-07-01  8:42   ` Paolo Bonzini
2016-06-30 20:54 ` [PATCH v1 06/11] KVM: x86: use hardware-compatible format for APIC ID register Radim Krčmář
2016-07-01  8:33   ` Paolo Bonzini
2016-07-01 13:11     ` Radim Krčmář
2016-07-01 14:12       ` Paolo Bonzini
2016-07-01 14:54         ` Radim Krčmář
2016-07-01 15:07           ` Paolo Bonzini
2016-07-01 15:53             ` Radim Krčmář
2016-07-01 16:37               ` Paolo Bonzini
2016-06-30 20:54 ` [PATCH v1 07/11] KVM: VMX: optimize APIC ID read with APICv Radim Krčmář
2016-07-01  8:42   ` Paolo Bonzini
2016-06-30 20:54 ` [PATCH v1 08/11] KVM: x86: directly call recalculate_apic_map on lapic restore Radim Krčmář
2016-07-01  8:43   ` Paolo Bonzini
2016-06-30 20:54 ` [PATCH v1 09/11] KVM: x86: reset lapic base in kvm_lapic_reset Radim Krčmář
2016-07-01  8:43   ` Paolo Bonzini
2016-06-30 20:54 ` [PATCH v1 10/11] KVM: x86: add KVM_CAP_X2APIC_API Radim Krčmář
2016-07-01  8:24   ` Paolo Bonzini
2016-07-01 13:25     ` Radim Krčmář
2016-07-01 18:09   ` David Matlack
2016-07-01 18:31     ` Radim Krčmář
2016-06-30 20:54 ` [PATCH v1 11/11] KVM: x86: bump MAX_VCPUS to 288 Radim Krčmář
2016-07-01  8:43   ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7f5a8277-f905-e6a2-fba8-7f859d300b66@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=jan.kiszka@web.de \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterx@redhat.com \
    --cc=rkrcmar@redhat.com \
    --cc=tianyu.lan@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.