From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758819AbbA2VuF (ORCPT ); Thu, 29 Jan 2015 16:50:05 -0500 Received: from mx1.redhat.com ([209.132.183.28]:58250 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758730AbbA2Vtu (ORCPT ); Thu, 29 Jan 2015 16:49:50 -0500 From: =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= To: linux-kernel@vger.kernel.org Cc: kvm@vger.kernel.org, Paolo Bonzini , Nadav Amit , Gleb Natapov Subject: [PATCH 8/8] KVM: x86: simplify kvm_apic_map Date: Thu, 29 Jan 2015 22:48:55 +0100 Message-Id: <1422568135-28402-9-git-send-email-rkrcmar@redhat.com> In-Reply-To: <1422568135-28402-1-git-send-email-rkrcmar@redhat.com> References: <1422568135-28402-1-git-send-email-rkrcmar@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org recalculate_apic_map() uses two passes over all VCPUs. This is a relic from time when we selected a global mode in the first pass and set up the optimized table in the second pass (to have a consistent mode). Recent changes made mixed mode unoptimized and we can do it in one pass. Format of logical MDA is a function of the mode, so we encode it in apic_logical_id() and drop obsoleted variables from the struct. Signed-off-by: Radim Krčmář --- arch/x86/include/asm/kvm_host.h | 3 -- arch/x86/kvm/lapic.c | 78 ++++++++++------------------------------- arch/x86/kvm/lapic.h | 29 ++++++++------- 3 files changed, 36 insertions(+), 74 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index fec3188cabbb..14b6b0fd17b1 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -555,9 +555,6 @@ struct kvm_arch_memory_slot { struct kvm_apic_map { struct rcu_head rcu; u8 mode; - u8 ldr_bits; - /* fields bellow are used to decode ldr values in different modes */ - u32 cid_shift, cid_mask, lid_mask; 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]; diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 621d9df6ac63..f74557791a77 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -146,49 +146,6 @@ static void recalculate_apic_map(struct kvm *kvm) if (!new) goto out; - new->ldr_bits = 8; - /* flat mode is default */ - new->cid_shift = 8; - new->cid_mask = 0; - new->lid_mask = 0xff; - - kvm_for_each_vcpu(i, vcpu, kvm) { - struct kvm_lapic *apic = vcpu->arch.apic; - - if (!kvm_apic_present(vcpu)) - continue; - - if (apic_x2apic_mode(apic)) { - new->ldr_bits = 32; - new->cid_shift = 16; - new->cid_mask = new->lid_mask = 0xffff; - new->mode |= KVM_APIC_MODE_X2APIC; - } else if (kvm_apic_get_reg(apic, APIC_LDR)) { - if (kvm_apic_get_reg(apic, APIC_DFR) == - APIC_DFR_CLUSTER) { - new->cid_shift = 4; - new->cid_mask = 0xf; - new->lid_mask = 0xf; - new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER; - } else { - new->cid_shift = 8; - new->cid_mask = 0; - new->lid_mask = 0xff; - new->mode |= KVM_APIC_MODE_XAPIC_FLAT; - } - } - - /* - * All APICs have to be configured in the same mode by an OS. - * We take advatage of this while building logical id loockup - * table. After reset APICs are in software disabled mode, so if - * we find apic with different setting we assume this is the mode - * OS wants all apics to be in; build lookup table accordingly. - */ - if (kvm_apic_sw_enabled(apic)) - break; - } - kvm_for_each_vcpu(i, vcpu, kvm) { struct kvm_lapic *apic = vcpu->arch.apic; u16 cid, lid; @@ -198,17 +155,22 @@ static void recalculate_apic_map(struct kvm *kvm) continue; aid = kvm_apic_id(apic); - ldr = kvm_apic_get_reg(apic, APIC_LDR); - cid = apic_cluster_id(new, ldr); - lid = apic_logical_id(new, ldr); - if (aid < ARRAY_SIZE(new->phys_map)) new->phys_map[aid] = apic; - /* The logical map is definitely wrong if we have multiple - * modes at the same time. Physical is still right though. - */ - if (hweight8(new->mode) != 1) + ldr = kvm_apic_get_reg(apic, APIC_LDR); + + if (apic_x2apic_mode(apic)) { + new->mode |= KVM_APIC_MODE_X2APIC; + } else if (ldr) { + ldr = GET_APIC_LOGICAL_ID(ldr); + if (kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_FLAT) + new->mode |= KVM_APIC_MODE_XAPIC_FLAT; + else + new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER; + } + + if (!apic_logical_id(new, ldr, &cid, &lid)) continue; if (lid && cid < ARRAY_SIZE(new->logical_map)) @@ -724,22 +686,20 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, dst = &map->phys_map[irq->dest_id]; } else { - u32 mda = irq->dest_id << (32 - map->ldr_bits); - u16 cid = apic_cluster_id(map, mda); + u16 cid; - if (cid >= ARRAY_SIZE(map->logical_map)) - goto out; - - if (hweight8(map->mode) != 1) { + if (!apic_logical_id(map, irq->dest_id, &cid, (u16 *)&bitmap)) + { /* Not deliverable with optimized map. */ ret = false; goto out; } + if (cid >= ARRAY_SIZE(map->logical_map)) + goto out; + dst = map->logical_map[cid]; - bitmap = apic_logical_id(map, mda); - if (irq->delivery_mode == APIC_DM_LOWEST) { int l = -1; for_each_set_bit(i, &bitmap, 16) { diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index fd0197a93862..320716e301a8 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -151,19 +151,24 @@ static inline bool kvm_apic_vid_enabled(struct kvm *kvm) return kvm_x86_ops->vm_has_apicv(kvm); } -static inline u16 apic_cluster_id(struct kvm_apic_map *map, u32 ldr) +static inline bool +apic_logical_id(struct kvm_apic_map *map, u32 ldr, u16 *cid, u16 *lid) { - u16 cid; - ldr >>= 32 - map->ldr_bits; - cid = (ldr >> map->cid_shift) & map->cid_mask; - - return cid; -} - -static inline u16 apic_logical_id(struct kvm_apic_map *map, u32 ldr) -{ - ldr >>= (32 - map->ldr_bits); - return ldr & map->lid_mask; + switch (map->mode) { + case KVM_APIC_MODE_XAPIC_FLAT: + *cid = 0; + *lid = ldr & 0xff; + return true; + case KVM_APIC_MODE_XAPIC_CLUSTER: + *cid = (ldr >> 4) & 0xf; + *lid = ldr & 0xf; + return true; + case KVM_APIC_MODE_X2APIC: + *cid = ldr >> 16; + *lid = ldr & 0xffff; + return true; + } + return false; } static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu) -- 2.2.2