linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Radim Krčmář" <rkrcmar@redhat.com>
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	"Lan, Tianyu" <tianyu.lan@intel.com>,
	Igor Mammedov <imammedo@redhat.com>,
	Jan Kiszka <jan.kiszka@web.de>, Peter Xu <peterx@redhat.com>,
	Yang Zhang <yang.zhang.wz@gmail.com>
Subject: [PATCH v3 03/14] KVM: x86: use physical LAPIC array for logical x2APIC
Date: Tue, 12 Jul 2016 22:09:19 +0200	[thread overview]
Message-ID: <20160712200930.32143-4-rkrcmar@redhat.com> (raw)
In-Reply-To: <20160712200930.32143-1-rkrcmar@redhat.com>

Logical x2APIC IDs map injectively to physical x2APIC IDs, so we can
reuse the physical array for them.  This allows us to save space by
separating logical xAPIC maps.

Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
---
 arch/x86/include/asm/kvm_host.h |  6 ++--
 arch/x86/kvm/lapic.c            | 69 +++++++++++++++++++++--------------------
 2 files changed, 39 insertions(+), 36 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 53d39771842b..3194b19b9c7b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -683,8 +683,10 @@ struct kvm_apic_map {
 	struct rcu_head rcu;
 	u8 mode;
 	struct kvm_lapic *phys_map[256];
-	/* first index is cluster id second is cpu id in a cluster */
-	struct kvm_lapic *logical_map[16][16];
+	union {
+		struct kvm_lapic *xapic_flat_map[8];
+		struct kvm_lapic *xapic_cluster_map[16][4];
+	};
 };
 
 /* Hyper-V emulation context */
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2987843657db..9880d03f533d 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -115,26 +115,36 @@ static inline int apic_enabled(struct kvm_lapic *apic)
 	(LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \
 	 APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
 
-/* The logical map is definitely wrong if we have multiple
- * modes at the same time.  (Physical map is always right.)
- */
-static inline bool kvm_apic_logical_map_valid(struct kvm_apic_map *map)
-{
-	return !(map->mode & (map->mode - 1));
-}
+static inline bool kvm_apic_map_get_logical_dest(struct kvm_apic_map *map,
+		u32 dest_id, struct kvm_lapic ***cluster, u16 *mask) {
+	switch (map->mode) {
+	case KVM_APIC_MODE_X2APIC: {
+		u32 offset = (dest_id >> 16) * 16;
+		u32 max_apic_id = ARRAY_SIZE(map->phys_map) - 1;
 
-static inline void
-apic_logical_id(struct kvm_apic_map *map, u32 dest_id, u16 *cid, u16 *lid)
-{
-	unsigned lid_bits;
+		if (offset <= max_apic_id) {
+			u8 cluster_size = min(max_apic_id - offset + 1, 16U);
 
-	BUILD_BUG_ON(KVM_APIC_MODE_XAPIC_CLUSTER !=  4);
-	BUILD_BUG_ON(KVM_APIC_MODE_XAPIC_FLAT    !=  8);
-	BUILD_BUG_ON(KVM_APIC_MODE_X2APIC        != 16);
-	lid_bits = map->mode;
+			*cluster = &map->phys_map[offset];
+			*mask = dest_id & (0xffff >> (16 - cluster_size));
+		} else {
+			*mask = 0;
+		}
 
-	*cid = dest_id >> lid_bits;
-	*lid = dest_id & ((1 << lid_bits) - 1);
+		return true;
+		}
+	case KVM_APIC_MODE_XAPIC_FLAT:
+		*cluster = map->xapic_flat_map;
+		*mask = dest_id & 0xff;
+		return true;
+	case KVM_APIC_MODE_XAPIC_CLUSTER:
+		*cluster = map->xapic_cluster_map[dest_id >> 4];
+		*mask = dest_id & 0xf;
+		return true;
+	default:
+		/* Not optimized. */
+		return false;
+	}
 }
 
 static void recalculate_apic_map(struct kvm *kvm)
@@ -152,7 +162,8 @@ static void recalculate_apic_map(struct kvm *kvm)
 
 	kvm_for_each_vcpu(i, vcpu, kvm) {
 		struct kvm_lapic *apic = vcpu->arch.apic;
-		u16 cid, lid;
+		struct kvm_lapic **cluster;
+		u16 mask;
 		u32 ldr, aid;
 
 		if (!kvm_apic_present(vcpu))
@@ -174,13 +185,11 @@ static void recalculate_apic_map(struct kvm *kvm)
 				new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER;
 		}
 
-		if (!kvm_apic_logical_map_valid(new))
+		if (!kvm_apic_map_get_logical_dest(new, ldr, &cluster, &mask))
 			continue;
 
-		apic_logical_id(new, ldr, &cid, &lid);
-
-		if (lid && cid < ARRAY_SIZE(new->logical_map))
-			new->logical_map[cid][ffs(lid) - 1] = apic;
+		if (mask)
+			cluster[ffs(mask) - 1] = apic;
 	}
 out:
 	old = rcu_dereference_protected(kvm->arch.apic_map,
@@ -685,7 +694,6 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
 {
 	int i, lowest;
 	bool x2apic_ipi;
-	u16 cid;
 
 	if (irq->shorthand == APIC_DEST_SELF && src) {
 		*dst = src;
@@ -711,18 +719,11 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
 		return true;
 	}
 
-	if (!kvm_apic_logical_map_valid(map))
+	*bitmap = 0;
+	if (!kvm_apic_map_get_logical_dest(map, irq->dest_id, dst,
+				(u16 *)bitmap))
 		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;
 
-- 
2.9.0

  parent reply	other threads:[~2016-07-12 20:10 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-12 20:09 [PATCH v3 00/14] KVM: x86: break the xAPIC barrier Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 01/14] KVM: x86: bump KVM_SOFT_MAX_VCPUS to 240 Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 02/14] KVM: x86: add kvm_apic_map_get_dest_lapic Radim Krčmář
2016-07-12 20:09 ` Radim Krčmář [this message]
2016-08-02 13:46   ` [PATCH v3 03/14] KVM: x86: use physical LAPIC array for logical x2APIC Wanpeng Li
2016-08-02 14:22     ` Radim Krčmář
2016-08-02 16:40       ` Nadav Amit
2016-07-12 20:09 ` [PATCH v3 04/14] KVM: x86: dynamic kvm_apic_map Radim Krčmář
2016-07-13  8:29   ` Paolo Bonzini
2016-07-13 14:37     ` Radim Krčmář
2016-08-02 11:39   ` Wanpeng Li
2016-08-02 12:22     ` Radim Krčmář
2016-08-02 13:15       ` Wanpeng Li
2016-07-12 20:09 ` [PATCH v3 05/14] KVM: x86: use generic function for MSI parsing Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 06/14] KVM: x86: use hardware-compatible format for APIC ID register Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 07/14] KVM: x86: reset APIC ID when enabling LAPIC Radim Krčmář
2016-08-02 13:26   ` Wanpeng Li
2016-08-02 13:52     ` Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 08/14] KVM: VMX: optimize APIC ID read with APICv Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 09/14] KVM: x86: reset lapic base in kvm_lapic_reset Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 10/14] KVM: pass struct kvm to kvm_set_routing_entry Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 11/14] KVM: x86: add KVM_CAP_X2APIC_API Radim Krčmář
2016-07-13  8:41   ` Paolo Bonzini
2016-07-13 14:40     ` Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 12/14] KVM: x86: add a flag to disable KVM x2apic broadcast quirk Radim Krčmář
2016-07-13  8:38   ` Paolo Bonzini
2016-07-13 15:14     ` Radim Krčmář
2016-07-13 15:30       ` Paolo Bonzini
2016-07-13 10:15   ` Paolo Bonzini
2016-07-13 14:52     ` Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 13/14] KVM: x86: bump MAX_VCPUS to 288 Radim Krčmář
2016-07-12 20:09 ` [PATCH v3 14/14] KVM: x86: bump KVM_MAX_VCPU_ID to 1023 Radim Krčmář

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=20160712200930.32143-4-rkrcmar@redhat.com \
    --to=rkrcmar@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=jan.kiszka@web.de \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=tianyu.lan@intel.com \
    --cc=yang.zhang.wz@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).