linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff
@ 2016-12-13 16:29 Radim Krčmář
  2016-12-13 16:29 ` [PATCH v2 1/4] KVM: x86: use delivery to self in hyperv synic Radim Krčmář
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Radim Krčmář @ 2016-12-13 16:29 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: Paolo Bonzini, Igor Mammedov, David Hildenbrand

v2 removes the capability that let userspace know of changes.

v1: http://www.spinics.net/lists/kvm/msg141944.html
> The problem is described in [4/4].
> 
> [1/4] is a prerequisite to allow a cleanup in [2/4].
> [2/4] hopefully makes [4/4] easier to understand.
> [3/4] fixes mistakes from dealing with the mixed mode.
> [4/4] allows the hotplug and and add a capability for it.


Radim Krčmář (4):
  KVM: x86: use delivery to self in hyperv synic
  KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  KVM: x86: make interrupt delivery fast and slow path behave the same
  KVM: x86: allow hotplug of VCPU with APIC ID over 0xff

 arch/x86/kvm/hyperv.c |  4 ++--
 arch/x86/kvm/lapic.c  | 62 ++++++++++++++++++++++++++++++++++++---------------
 arch/x86/kvm/lapic.h  | 11 ---------
 3 files changed, 46 insertions(+), 31 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/4] KVM: x86: use delivery to self in hyperv synic
  2016-12-13 16:29 [PATCH v2 0/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff Radim Krčmář
@ 2016-12-13 16:29 ` Radim Krčmář
  2016-12-13 16:29 ` [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id Radim Krčmář
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Radim Krčmář @ 2016-12-13 16:29 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: Paolo Bonzini, Igor Mammedov, David Hildenbrand

Interrupt to self can be sent without knowing the APIC ID.

Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
---
 v2: r-b David

 arch/x86/kvm/hyperv.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 99cde5220e07..313957ec9a9d 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -305,13 +305,13 @@ static int synic_set_irq(struct kvm_vcpu_hv_synic *synic, u32 sint)
 		return -ENOENT;
 
 	memset(&irq, 0, sizeof(irq));
-	irq.dest_id = kvm_apic_id(vcpu->arch.apic);
+	irq.shorthand = APIC_DEST_SELF;
 	irq.dest_mode = APIC_DEST_PHYSICAL;
 	irq.delivery_mode = APIC_DM_FIXED;
 	irq.vector = vector;
 	irq.level = 1;
 
-	ret = kvm_irq_delivery_to_apic(vcpu->kvm, NULL, &irq, NULL);
+	ret = kvm_irq_delivery_to_apic(vcpu->kvm, vcpu->arch.apic, &irq, NULL);
 	trace_kvm_hv_synic_set_irq(vcpu->vcpu_id, sint, irq.vector, ret);
 	return ret;
 }
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-13 16:29 [PATCH v2 0/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff Radim Krčmář
  2016-12-13 16:29 ` [PATCH v2 1/4] KVM: x86: use delivery to self in hyperv synic Radim Krčmář
@ 2016-12-13 16:29 ` Radim Krčmář
  2016-12-14 12:39   ` David Hildenbrand
  2016-12-14 16:15   ` David Hildenbrand
  2016-12-13 16:30 ` [PATCH v2 3/4] KVM: x86: make interrupt delivery fast and slow path behave the same Radim Krčmář
  2016-12-13 16:30 ` [PATCH v2 4/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff Radim Krčmář
  3 siblings, 2 replies; 13+ messages in thread
From: Radim Krčmář @ 2016-12-13 16:29 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: Paolo Bonzini, Igor Mammedov, David Hildenbrand

There were three calls sites:
 - recalculate_apic_map and kvm_apic_match_physical_addr, where it would
   only complicate implementation of x2APIC hotplug;
 - in apic_debug, where it was still somewhat preserved, but keeping the
   old function just for apic_debug was not worth it

Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
---
 arch/x86/kvm/lapic.c | 41 ++++++++++++++++++++++++++++++-----------
 arch/x86/kvm/lapic.h | 11 -----------
 2 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 09edd32b8e42..e645b4bc6437 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -115,6 +115,16 @@ 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)
 
+static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
+{
+	return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
+}
+
+static inline u32 kvm_x2apic_id(struct kvm_lapic *apic)
+{
+	return apic->vcpu->vcpu_id;
+}
+
 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) {
@@ -159,13 +169,13 @@ static void recalculate_apic_map(struct kvm *kvm)
 	struct kvm_apic_map *new, *old = NULL;
 	struct kvm_vcpu *vcpu;
 	int i;
-	u32 max_id = 255;
+	u32 max_id = 256; /* enough space for any xAPIC ID */
 
 	mutex_lock(&kvm->arch.apic_map_lock);
 
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		if (kvm_apic_present(vcpu))
-			max_id = max(max_id, kvm_apic_id(vcpu->arch.apic));
+			max_id = max(max_id, kvm_x2apic_id(vcpu->arch.apic));
 
 	new = kvm_kvzalloc(sizeof(struct kvm_apic_map) +
 	                   sizeof(struct kvm_lapic *) * ((u64)max_id + 1));
@@ -179,16 +189,23 @@ static void recalculate_apic_map(struct kvm *kvm)
 		struct kvm_lapic *apic = vcpu->arch.apic;
 		struct kvm_lapic **cluster;
 		u16 mask;
-		u32 ldr, aid;
+		u32 ldr;
+		u8 xapic_id;
+		u32 x2apic_id;
 
 		if (!kvm_apic_present(vcpu))
 			continue;
 
-		aid = kvm_apic_id(apic);
-		ldr = kvm_lapic_get_reg(apic, APIC_LDR);
+		xapic_id = kvm_xapic_id(apic);
+		x2apic_id = kvm_x2apic_id(apic);
 
-		if (aid <= new->max_apic_id)
-			new->phys_map[aid] = apic;
+		if (apic_x2apic_mode(apic) &&
+				x2apic_id <= new->max_apic_id)
+			new->phys_map[x2apic_id] = apic;
+		else if (!apic_x2apic_mode(apic))
+			new->phys_map[xapic_id] = apic;
+
+		ldr = kvm_lapic_get_reg(apic, APIC_LDR);
 
 		if (apic_x2apic_mode(apic)) {
 			new->mode |= KVM_APIC_MODE_X2APIC;
@@ -250,6 +267,8 @@ static inline void kvm_apic_set_x2apic_id(struct kvm_lapic *apic, u32 id)
 {
 	u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf));
 
+	WARN_ON_ONCE(id != apic->vcpu->vcpu_id);
+
 	kvm_lapic_set_reg(apic, APIC_ID, id);
 	kvm_lapic_set_reg(apic, APIC_LDR, ldr);
 	recalculate_apic_map(apic->vcpu->kvm);
@@ -591,9 +610,9 @@ static bool kvm_apic_match_physical_addr(struct kvm_lapic *apic, u32 mda)
 		return true;
 
 	if (apic_x2apic_mode(apic))
-		return mda == kvm_apic_id(apic);
+		return mda == kvm_x2apic_id(apic);
 
-	return mda == SET_APIC_DEST_FIELD(kvm_apic_id(apic));
+	return mda == SET_APIC_DEST_FIELD(kvm_xapic_id(apic));
 }
 
 static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda)
@@ -1907,9 +1926,9 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
 	vcpu->arch.apic_arb_prio = 0;
 	vcpu->arch.apic_attention = 0;
 
-	apic_debug("%s: vcpu=%p, id=%d, base_msr="
+	apic_debug("%s: vcpu=%p, id=0x%x, base_msr="
 		   "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__,
-		   vcpu, kvm_apic_id(apic),
+		   vcpu, kvm_lapic_get_reg(apic, APIC_ID),
 		   vcpu->arch.apic_base, apic->base_address);
 }
 
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index e0c80233b3e1..cb16e6fd2330 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -202,17 +202,6 @@ static inline int kvm_lapic_latched_init(struct kvm_vcpu *vcpu)
 	return lapic_in_kernel(vcpu) && test_bit(KVM_APIC_INIT, &vcpu->arch.apic->pending_events);
 }
 
-static inline u32 kvm_apic_id(struct kvm_lapic *apic)
-{
-	/* To avoid a race between apic_base and following APIC_ID update when
-	 * switching to x2apic_mode, the x2apic mode returns initial x2apic id.
-	 */
-	if (apic_x2apic_mode(apic))
-		return apic->vcpu->vcpu_id;
-
-	return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
-}
-
 bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
 
 void wait_lapic_expire(struct kvm_vcpu *vcpu);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/4] KVM: x86: make interrupt delivery fast and slow path behave the same
  2016-12-13 16:29 [PATCH v2 0/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff Radim Krčmář
  2016-12-13 16:29 ` [PATCH v2 1/4] KVM: x86: use delivery to self in hyperv synic Radim Krčmář
  2016-12-13 16:29 ` [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id Radim Krčmář
@ 2016-12-13 16:30 ` Radim Krčmář
  2016-12-13 16:30 ` [PATCH v2 4/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff Radim Krčmář
  3 siblings, 0 replies; 13+ messages in thread
From: Radim Krčmář @ 2016-12-13 16:30 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: Paolo Bonzini, Igor Mammedov, David Hildenbrand

Slow path tried to prevent IPIs from x2APIC VCPUs from being delivered
to xAPIC VCPUs and vice-versa.  Make slow path behave like fast path,
which never distinguished that.

Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
---
 arch/x86/kvm/lapic.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index e645b4bc6437..bc8df7ce2766 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -612,7 +612,7 @@ static bool kvm_apic_match_physical_addr(struct kvm_lapic *apic, u32 mda)
 	if (apic_x2apic_mode(apic))
 		return mda == kvm_x2apic_id(apic);
 
-	return mda == SET_APIC_DEST_FIELD(kvm_xapic_id(apic));
+	return mda == kvm_xapic_id(apic);
 }
 
 static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda)
@@ -629,7 +629,6 @@ static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda)
 		       && (logical_id & mda & 0xffff) != 0;
 
 	logical_id = GET_APIC_LOGICAL_ID(logical_id);
-	mda = GET_APIC_DEST_FIELD(mda);
 
 	switch (kvm_lapic_get_reg(apic, APIC_DFR)) {
 	case APIC_DFR_FLAT:
@@ -646,9 +645,9 @@ static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda)
 
 /* The KVM local APIC implementation has two quirks:
  *
- *  - the xAPIC MDA stores the destination at bits 24-31, while this
- *    is not true of struct kvm_lapic_irq's dest_id field.  This is
- *    just a quirk in the API and is not problematic.
+ *  - Real hardware delivers interrupts destined to x2APIC ID > 0xff to LAPICs
+ *    in xAPIC mode if the "destination & 0xff" matches its xAPIC ID.
+ *    KVM doesn't do that aliasing.
  *
  *  - in-kernel IOAPIC messages have to be delivered directly to
  *    x2APIC, because the kernel does not support interrupt remapping.
@@ -664,13 +663,12 @@ static u32 kvm_apic_mda(struct kvm_vcpu *vcpu, unsigned int dest_id,
 		struct kvm_lapic *source, struct kvm_lapic *target)
 {
 	bool ipi = source != NULL;
-	bool x2apic_mda = apic_x2apic_mode(ipi ? source : target);
 
 	if (!vcpu->kvm->arch.x2apic_broadcast_quirk_disabled &&
-	    !ipi && dest_id == APIC_BROADCAST && x2apic_mda)
+	    !ipi && dest_id == APIC_BROADCAST && apic_x2apic_mode(target))
 		return X2APIC_BROADCAST;
 
-	return x2apic_mda ? dest_id : SET_APIC_DEST_FIELD(dest_id);
+	return dest_id;
 }
 
 bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 4/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff
  2016-12-13 16:29 [PATCH v2 0/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff Radim Krčmář
                   ` (2 preceding siblings ...)
  2016-12-13 16:30 ` [PATCH v2 3/4] KVM: x86: make interrupt delivery fast and slow path behave the same Radim Krčmář
@ 2016-12-13 16:30 ` Radim Krčmář
  3 siblings, 0 replies; 13+ messages in thread
From: Radim Krčmář @ 2016-12-13 16:30 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: Paolo Bonzini, Igor Mammedov, David Hildenbrand

LAPIC after reset is in xAPIC mode, which poses a problem for hotplug of
VCPUs with high APIC ID, because reset VCPU is waiting for INIT/SIPI,
but there is no way to uniquely address it using xAPIC.

>From many possible options, we chose the one that also works on real
hardware: accepting interrupts addressed to LAPIC's x2APIC ID even in
xAPIC mode.

KVM intentionally differs from real hardware, because real hardware
(Knights Landing) does just "x2apic_id & 0xff" to decide whether to
accept the interrupt in xAPIC mode and it can deliver one interrupt to
more than one physical destination, e.g. 0x123 to 0x123 and 0x23.

Fixes: 682f732ecf73 ("KVM: x86: bump MAX_VCPUS to 288")
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
---
 v2:
 * Do not add capability [David, Paolo]
 * Tag it as a fix [David]
---
 arch/x86/kvm/lapic.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index bc8df7ce2766..f1b22bb76a4a 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -199,10 +199,15 @@ static void recalculate_apic_map(struct kvm *kvm)
 		xapic_id = kvm_xapic_id(apic);
 		x2apic_id = kvm_x2apic_id(apic);
 
-		if (apic_x2apic_mode(apic) &&
+		/* Hotplug hack: see kvm_apic_match_physical_addr(), ... */
+		if ((apic_x2apic_mode(apic) || x2apic_id > 0xff) &&
 				x2apic_id <= new->max_apic_id)
 			new->phys_map[x2apic_id] = apic;
-		else if (!apic_x2apic_mode(apic))
+		/*
+		 * ... xAPIC ID of VCPUs with APIC ID > 0xff will wrap-around,
+		 * prevent them from masking VCPUs with APIC ID <= 0xff.
+		 */
+		if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id])
 			new->phys_map[xapic_id] = apic;
 
 		ldr = kvm_lapic_get_reg(apic, APIC_LDR);
@@ -612,6 +617,10 @@ static bool kvm_apic_match_physical_addr(struct kvm_lapic *apic, u32 mda)
 	if (apic_x2apic_mode(apic))
 		return mda == kvm_x2apic_id(apic);
 
+	/* Hotplug hack: LAPIC in xAPIC mode also accepts x2APIC. */
+	if (kvm_x2apic_id(apic) > 0xff && mda == kvm_x2apic_id(apic))
+		return true;
+
 	return mda == kvm_xapic_id(apic);
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-13 16:29 ` [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id Radim Krčmář
@ 2016-12-14 12:39   ` David Hildenbrand
  2016-12-14 13:41     ` Radim Krčmář
  2016-12-14 16:15   ` David Hildenbrand
  1 sibling, 1 reply; 13+ messages in thread
From: David Hildenbrand @ 2016-12-14 12:39 UTC (permalink / raw)
  To: Radim Krčmář, linux-kernel, kvm
  Cc: Paolo Bonzini, Igor Mammedov

Am 13.12.2016 um 17:29 schrieb Radim Krčmář:
> There were three calls sites:
>  - recalculate_apic_map and kvm_apic_match_physical_addr, where it would
>    only complicate implementation of x2APIC hotplug;
>  - in apic_debug, where it was still somewhat preserved, but keeping the
>    old function just for apic_debug was not worth it
>
> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
> ---
>  arch/x86/kvm/lapic.c | 41 ++++++++++++++++++++++++++++++-----------
>  arch/x86/kvm/lapic.h | 11 -----------
>  2 files changed, 30 insertions(+), 22 deletions(-)
>
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index 09edd32b8e42..e645b4bc6437 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -115,6 +115,16 @@ 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)
>
> +static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
> +{
> +	return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
> +}
> +
> +static inline u32 kvm_x2apic_id(struct kvm_lapic *apic)
> +{
> +	return apic->vcpu->vcpu_id;
> +}
> +
>  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) {
> @@ -159,13 +169,13 @@ static void recalculate_apic_map(struct kvm *kvm)
>  	struct kvm_apic_map *new, *old = NULL;
>  	struct kvm_vcpu *vcpu;
>  	int i;
> -	u32 max_id = 255;
> +	u32 max_id = 256; /* enough space for any xAPIC ID */

Why exactly do we have to increase this?

I thought the maximum xapic id is 255, and we correctly allocate
255+1 slots.

Now, we would allocate 257 slots and set max_apic_id to 256.

Can you elaborate?


-- 

David

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-14 12:39   ` David Hildenbrand
@ 2016-12-14 13:41     ` Radim Krčmář
  2016-12-14 15:50       ` Paolo Bonzini
  0 siblings, 1 reply; 13+ messages in thread
From: Radim Krčmář @ 2016-12-14 13:41 UTC (permalink / raw)
  To: David Hildenbrand; +Cc: linux-kernel, kvm, Paolo Bonzini, Igor Mammedov

2016-12-14 13:39+0100, David Hildenbrand:
> Am 13.12.2016 um 17:29 schrieb Radim Krčmář:
>> There were three calls sites:
>>  - recalculate_apic_map and kvm_apic_match_physical_addr, where it would
>>    only complicate implementation of x2APIC hotplug;
>>  - in apic_debug, where it was still somewhat preserved, but keeping the
>>    old function just for apic_debug was not worth it
>> 
>> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
>> ---
>>  arch/x86/kvm/lapic.c | 41 ++++++++++++++++++++++++++++++-----------
>>  arch/x86/kvm/lapic.h | 11 -----------
>>  2 files changed, 30 insertions(+), 22 deletions(-)
>> 
>> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
>> index 09edd32b8e42..e645b4bc6437 100644
>> --- a/arch/x86/kvm/lapic.c
>> +++ b/arch/x86/kvm/lapic.c
>> @@ -115,6 +115,16 @@ 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)
>> 
>> +static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
>> +{
>> +	return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
>> +}
>> +
>> +static inline u32 kvm_x2apic_id(struct kvm_lapic *apic)
>> +{
>> +	return apic->vcpu->vcpu_id;
>> +}
>> +
>>  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) {
>> @@ -159,13 +169,13 @@ static void recalculate_apic_map(struct kvm *kvm)
>>  	struct kvm_apic_map *new, *old = NULL;
>>  	struct kvm_vcpu *vcpu;
>>  	int i;
>> -	u32 max_id = 255;
>> +	u32 max_id = 256; /* enough space for any xAPIC ID */
> 
> Why exactly do we have to increase this?
> 
> I thought the maximum xapic id is 255, and we correctly allocate
> 255+1 slots.
> 
> Now, we would allocate 257 slots and set max_apic_id to 256.

Right, it is a typical off-by-one error.  The comment is sufficient ...

Queued for v3,
Thanks.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-14 13:41     ` Radim Krčmář
@ 2016-12-14 15:50       ` Paolo Bonzini
  0 siblings, 0 replies; 13+ messages in thread
From: Paolo Bonzini @ 2016-12-14 15:50 UTC (permalink / raw)
  To: Radim Krčmář, David Hildenbrand
  Cc: linux-kernel, kvm, Igor Mammedov



On 14/12/2016 14:41, Radim Krčmář wrote:
> 2016-12-14 13:39+0100, David Hildenbrand:
>> Am 13.12.2016 um 17:29 schrieb Radim Krčmář:
>>> There were three calls sites:
>>>  - recalculate_apic_map and kvm_apic_match_physical_addr, where it would
>>>    only complicate implementation of x2APIC hotplug;
>>>  - in apic_debug, where it was still somewhat preserved, but keeping the
>>>    old function just for apic_debug was not worth it
>>>
>>> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
>>> ---
>>>  arch/x86/kvm/lapic.c | 41 ++++++++++++++++++++++++++++++-----------
>>>  arch/x86/kvm/lapic.h | 11 -----------
>>>  2 files changed, 30 insertions(+), 22 deletions(-)
>>>
>>> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
>>> index 09edd32b8e42..e645b4bc6437 100644
>>> --- a/arch/x86/kvm/lapic.c
>>> +++ b/arch/x86/kvm/lapic.c
>>> @@ -115,6 +115,16 @@ 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)
>>>
>>> +static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
>>> +{
>>> +	return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
>>> +}
>>> +
>>> +static inline u32 kvm_x2apic_id(struct kvm_lapic *apic)
>>> +{
>>> +	return apic->vcpu->vcpu_id;
>>> +}
>>> +
>>>  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) {
>>> @@ -159,13 +169,13 @@ static void recalculate_apic_map(struct kvm *kvm)
>>>  	struct kvm_apic_map *new, *old = NULL;
>>>  	struct kvm_vcpu *vcpu;
>>>  	int i;
>>> -	u32 max_id = 255;
>>> +	u32 max_id = 256; /* enough space for any xAPIC ID */
>>
>> Why exactly do we have to increase this?
>>
>> I thought the maximum xapic id is 255, and we correctly allocate
>> 255+1 slots.
>>
>> Now, we would allocate 257 slots and set max_apic_id to 256.
> 
> Right, it is a typical off-by-one error.  The comment is sufficient ...

I can change it myself too.

Paolo

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-13 16:29 ` [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id Radim Krčmář
  2016-12-14 12:39   ` David Hildenbrand
@ 2016-12-14 16:15   ` David Hildenbrand
  2016-12-14 16:59     ` Paolo Bonzini
  2016-12-14 17:12     ` Radim Krčmář
  1 sibling, 2 replies; 13+ messages in thread
From: David Hildenbrand @ 2016-12-14 16:15 UTC (permalink / raw)
  To: Radim Krčmář, linux-kernel, kvm
  Cc: Paolo Bonzini, Igor Mammedov


>  	kvm_for_each_vcpu(i, vcpu, kvm)
>  		if (kvm_apic_present(vcpu))
> -			max_id = max(max_id, kvm_apic_id(vcpu->arch.apic));
> +			max_id = max(max_id, kvm_x2apic_id(vcpu->arch.apic));
>
>  	new = kvm_kvzalloc(sizeof(struct kvm_apic_map) +
>  	                   sizeof(struct kvm_lapic *) * ((u64)max_id + 1));
> @@ -179,16 +189,23 @@ static void recalculate_apic_map(struct kvm *kvm)
>  		struct kvm_lapic *apic = vcpu->arch.apic;
>  		struct kvm_lapic **cluster;
>  		u16 mask;
> -		u32 ldr, aid;
> +		u32 ldr;
> +		u8 xapic_id;
> +		u32 x2apic_id;
>
>  		if (!kvm_apic_present(vcpu))
>  			continue;
>
> -		aid = kvm_apic_id(apic);

think I'd even prefer here a simple

aid = kvm_xapic_id(apic);
if (apic_x2apic_mode(apic))
	aid = kvm_x2apic_id(apic);

that would keep changes minimal and I don't really see any benefit in 
the code when splitting handling up.

Patch 4 then simply can fixup setting code

if (aid <= new->max_apic_id && !new->phys_map[aid])
	new->phys_map[aid] = apic;

(if I am not missing some important corner case here)


> -		ldr = kvm_lapic_get_reg(apic, APIC_LDR);
> +		xapic_id = kvm_xapic_id(apic);
> +		x2apic_id = kvm_x2apic_id(apic);
>
> -		if (aid <= new->max_apic_id)
> -			new->phys_map[aid] = apic;
> +		if (apic_x2apic_mode(apic) &&
> +				x2apic_id <= new->max_apic_id)
> +			new->phys_map[x2apic_id] = apic;
> +		else if (!apic_x2apic_mode(apic))


This looks good to me.

-- 

David

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-14 16:15   ` David Hildenbrand
@ 2016-12-14 16:59     ` Paolo Bonzini
  2016-12-14 17:15       ` Radim Krčmář
  2016-12-14 17:12     ` Radim Krčmář
  1 sibling, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2016-12-14 16:59 UTC (permalink / raw)
  To: David Hildenbrand, Radim Krčmář, linux-kernel, kvm
  Cc: Igor Mammedov



On 14/12/2016 17:15, David Hildenbrand wrote:
> 
>>      kvm_for_each_vcpu(i, vcpu, kvm)
>>          if (kvm_apic_present(vcpu))
>> -            max_id = max(max_id, kvm_apic_id(vcpu->arch.apic));
>> +            max_id = max(max_id, kvm_x2apic_id(vcpu->arch.apic));
>>
>>      new = kvm_kvzalloc(sizeof(struct kvm_apic_map) +
>>                         sizeof(struct kvm_lapic *) * ((u64)max_id + 1));
>> @@ -179,16 +189,23 @@ static void recalculate_apic_map(struct kvm *kvm)
>>          struct kvm_lapic *apic = vcpu->arch.apic;
>>          struct kvm_lapic **cluster;
>>          u16 mask;
>> -        u32 ldr, aid;
>> +        u32 ldr;
>> +        u8 xapic_id;
>> +        u32 x2apic_id;
>>
>>          if (!kvm_apic_present(vcpu))
>>              continue;
>>
>> -        aid = kvm_apic_id(apic);
> 
> think I'd even prefer here a simple
> 
> aid = kvm_xapic_id(apic);
> if (apic_x2apic_mode(apic))
>     aid = kvm_x2apic_id(apic);
> 
> that would keep changes minimal and I don't really see any benefit in
> the code when splitting handling up.
> 
> Patch 4 then simply can fixup setting code
> 
> if (aid <= new->max_apic_id && !new->phys_map[aid])
>     new->phys_map[aid] = apic;
> 
> (if I am not missing some important corner case here)

Radim, what do you think?  I wanted to get these in before Christmas,
but it's your call.

Paolo

> 
>> -        ldr = kvm_lapic_get_reg(apic, APIC_LDR);
>> +        xapic_id = kvm_xapic_id(apic);
>> +        x2apic_id = kvm_x2apic_id(apic);
>>
>> -        if (aid <= new->max_apic_id)
>> -            new->phys_map[aid] = apic;
>> +        if (apic_x2apic_mode(apic) &&
>> +                x2apic_id <= new->max_apic_id)
>> +            new->phys_map[x2apic_id] = apic;
>> +        else if (!apic_x2apic_mode(apic))
> 
> 
> This looks good to me.
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-14 16:15   ` David Hildenbrand
  2016-12-14 16:59     ` Paolo Bonzini
@ 2016-12-14 17:12     ` Radim Krčmář
  2016-12-14 17:26       ` David Hildenbrand
  1 sibling, 1 reply; 13+ messages in thread
From: Radim Krčmář @ 2016-12-14 17:12 UTC (permalink / raw)
  To: David Hildenbrand; +Cc: linux-kernel, kvm, Paolo Bonzini, Igor Mammedov

2016-12-14 17:15+0100, David Hildenbrand:
>>  	kvm_for_each_vcpu(i, vcpu, kvm)
>>  		if (kvm_apic_present(vcpu))
>> -			max_id = max(max_id, kvm_apic_id(vcpu->arch.apic));
>> +			max_id = max(max_id, kvm_x2apic_id(vcpu->arch.apic));
>> 
>>  	new = kvm_kvzalloc(sizeof(struct kvm_apic_map) +
>>  	                   sizeof(struct kvm_lapic *) * ((u64)max_id + 1));
>> @@ -179,16 +189,23 @@ static void recalculate_apic_map(struct kvm *kvm)
>>  		struct kvm_lapic *apic = vcpu->arch.apic;
>>  		struct kvm_lapic **cluster;
>>  		u16 mask;
>> -		u32 ldr, aid;
>> +		u32 ldr;
>> +		u8 xapic_id;
>> +		u32 x2apic_id;
>> 
>>  		if (!kvm_apic_present(vcpu))
>>  			continue;
>> 
>> -		aid = kvm_apic_id(apic);
> 
> think I'd even prefer here a simple
> 
> aid = kvm_xapic_id(apic);
> if (apic_x2apic_mode(apic))
> 	aid = kvm_x2apic_id(apic);
> 
> that would keep changes minimal and I don't really see any benefit in the
> code when splitting handling up.

It is neccesassary to write an entry for both IDs and I wanted to split
it before [4/4], because doing both changes at once seemed hard to
grasp.

Putting it here didn't work well either ... is a separate patch for the
hunk below better, or would you prefer to have it in [4/4]?

> Patch 4 then simply can fixup setting code
> 
> if (aid <= new->max_apic_id && !new->phys_map[aid])
> 	new->phys_map[aid] = apic;
> 
> (if I am not missing some important corner case here)

The trick is that we want to do the following even in xAPIC mode:

  new->phys_map[kvm_x2apic_id(apic)] = apic;

This is the main idea of the hotplug hack -- to allow unique addressing
of processors that were reset in xAPIC mode.  (And I add a disgusting
"x2apic_id > 0xff" condition in [4/4], because we still allow guests to
change xAPIC IDs, which wouldn't play nice with this.)

Hardware does a superset of this, because it only looks at lower 8 bits
of the desination ID when delivering to xAPIC.

When kvm_x2apic_id(apic) != kvm_xapic_id(apic), then the APIC is in
xAPIC mode so we definitely want to keep xAPIC working, hence

  if (!apic_x2apic_mode(apic))
  	new->phys_map[kvm_xapic_id(apic)] = apic;

Two writes are necessary.

And there can already be another_apic "kvm_x2apic_id(another_apic) ==
kvm_xapic_id(apic)" so we prevent hotplug from breaking existing x2APIC
setups by doing "!new->phys_map[aid]" when setting xAPIC ID.

I hope we get a better solution in the future, but it would have to be
done at hardware (QEMU) level, because even firmware (seabios) doesn't
have standard ways to deal with this situation ...

>> -		ldr = kvm_lapic_get_reg(apic, APIC_LDR);
>> +		xapic_id = kvm_xapic_id(apic);
>> +		x2apic_id = kvm_x2apic_id(apic);
>> 
>> -		if (aid <= new->max_apic_id)
>> -			new->phys_map[aid] = apic;
>> +		if (apic_x2apic_mode(apic) &&
>> +				x2apic_id <= new->max_apic_id)
>> +			new->phys_map[x2apic_id] = apic;
>> +		else if (!apic_x2apic_mode(apic))
> 
> 
> This looks good to me.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-14 16:59     ` Paolo Bonzini
@ 2016-12-14 17:15       ` Radim Krčmář
  0 siblings, 0 replies; 13+ messages in thread
From: Radim Krčmář @ 2016-12-14 17:15 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: David Hildenbrand, linux-kernel, kvm, Igor Mammedov

2016-12-14 17:59+0100, Paolo Bonzini:
> On 14/12/2016 17:15, David Hildenbrand wrote:
>> 
>>>      kvm_for_each_vcpu(i, vcpu, kvm)
>>>          if (kvm_apic_present(vcpu))
>>> -            max_id = max(max_id, kvm_apic_id(vcpu->arch.apic));
>>> +            max_id = max(max_id, kvm_x2apic_id(vcpu->arch.apic));
>>>
>>>      new = kvm_kvzalloc(sizeof(struct kvm_apic_map) +
>>>                         sizeof(struct kvm_lapic *) * ((u64)max_id + 1));
>>> @@ -179,16 +189,23 @@ static void recalculate_apic_map(struct kvm *kvm)
>>>          struct kvm_lapic *apic = vcpu->arch.apic;
>>>          struct kvm_lapic **cluster;
>>>          u16 mask;
>>> -        u32 ldr, aid;
>>> +        u32 ldr;
>>> +        u8 xapic_id;
>>> +        u32 x2apic_id;
>>>
>>>          if (!kvm_apic_present(vcpu))
>>>              continue;
>>>
>>> -        aid = kvm_apic_id(apic);
>> 
>> think I'd even prefer here a simple
>> 
>> aid = kvm_xapic_id(apic);
>> if (apic_x2apic_mode(apic))
>>     aid = kvm_x2apic_id(apic);
>> 
>> that would keep changes minimal and I don't really see any benefit in
>> the code when splitting handling up.
>> 
>> Patch 4 then simply can fixup setting code
>> 
>> if (aid <= new->max_apic_id && !new->phys_map[aid])
>>     new->phys_map[aid] = apic;
>> 
>> (if I am not missing some important corner case here)
> 
> Radim, what do you think?  I wanted to get these in before Christmas,
> but it's your call.

There was a reason why it was so ugly ... it's not a hack for nothing.

I can hope to make the patches/code more understandable, but the
function shouldn't change, unless we want to take a different approach.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id
  2016-12-14 17:12     ` Radim Krčmář
@ 2016-12-14 17:26       ` David Hildenbrand
  0 siblings, 0 replies; 13+ messages in thread
From: David Hildenbrand @ 2016-12-14 17:26 UTC (permalink / raw)
  To: Radim Krčmář
  Cc: linux-kernel, kvm, Paolo Bonzini, Igor Mammedov


>> think I'd even prefer here a simple
>>
>> aid = kvm_xapic_id(apic);
>> if (apic_x2apic_mode(apic))
>> 	aid = kvm_x2apic_id(apic);
>>
>> that would keep changes minimal and I don't really see any benefit in the
>> code when splitting handling up.
>
> It is neccesassary to write an entry for both IDs and I wanted to split
> it before [4/4], because doing both changes at once seemed hard to
> grasp.
>
> Putting it here didn't work well either ... is a separate patch for the
> hunk below better, or would you prefer to have it in [4/4]?

I actually would prefer to have it in 4/4, but not sure if it is worth 
yet another round. Anyhow,

Reviewed-by: David Hildenbrand <david@redhat.com>

for this patch (with the 256 fixed)

>
>> Patch 4 then simply can fixup setting code
>>
>> if (aid <= new->max_apic_id && !new->phys_map[aid])
>> 	new->phys_map[aid] = apic;
>>
>> (if I am not missing some important corner case here)
>
> The trick is that we want to do the following even in xAPIC mode:
>
>   new->phys_map[kvm_x2apic_id(apic)] = apic;
>
> This is the main idea of the hotplug hack -- to allow unique addressing
> of processors that were reset in xAPIC mode.  (And I add a disgusting
> "x2apic_id > 0xff" condition in [4/4], because we still allow guests to
> change xAPIC IDs, which wouldn't play nice with this.)
>
> Hardware does a superset of this, because it only looks at lower 8 bits
> of the desination ID when delivering to xAPIC.
>
> When kvm_x2apic_id(apic) != kvm_xapic_id(apic), then the APIC is in
> xAPIC mode so we definitely want to keep xAPIC working, hence
>
>   if (!apic_x2apic_mode(apic))
>   	new->phys_map[kvm_xapic_id(apic)] = apic;

Okay, so this is is the case I missed in patch 4 :)

Thanks for the explanation and sorry for the noise.

-- 

David

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-12-14 17:26 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-13 16:29 [PATCH v2 0/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff Radim Krčmář
2016-12-13 16:29 ` [PATCH v2 1/4] KVM: x86: use delivery to self in hyperv synic Radim Krčmář
2016-12-13 16:29 ` [PATCH v2 2/4] KVM: x86: replace kvm_apic_id with kvm_{x,x2}apic_id Radim Krčmář
2016-12-14 12:39   ` David Hildenbrand
2016-12-14 13:41     ` Radim Krčmář
2016-12-14 15:50       ` Paolo Bonzini
2016-12-14 16:15   ` David Hildenbrand
2016-12-14 16:59     ` Paolo Bonzini
2016-12-14 17:15       ` Radim Krčmář
2016-12-14 17:12     ` Radim Krčmář
2016-12-14 17:26       ` David Hildenbrand
2016-12-13 16:30 ` [PATCH v2 3/4] KVM: x86: make interrupt delivery fast and slow path behave the same Radim Krčmář
2016-12-13 16:30 ` [PATCH v2 4/4] KVM: x86: allow hotplug of VCPU with APIC ID over 0xff Radim Krčmář

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).