Skip to contentSkip to conversation

x86: increase NR_IRQS and nr_irqs

PATCH In review Yinghai Lu 6 participants 44 messages Dec 25, 2009 – Jan 5, 2010

Subsystems (3)
lore
Share & tools
lore

Yinghai Lu

author
#0 lore raw

PATCH 1/1 x86: increase NR_IRQS and nr_irqs

have a system with lots of igb and ixgbe, when iov/vf are enabled for them, we hit the limit of 3064.

so try to increase NR_IRQS and nr_irqs to about 8000 and 6000. for that system.

---
 arch/x86/include/asm/irq_vectors.h |   12 ++++++------
 arch/x86/kernel/apic/io_apic.c     |    2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/include/asm/irq_vectors.h +6 -6
Index: linux-2.6/arch/x86/include/asm/irq_vectors.h
===================================================================
@@ -154,21 +154,21 @@ static inline int invalid_vm86_irq(int i
 
 #define NR_IRQS_LEGACY			  16
 
-#define CPU_VECTOR_LIMIT		(  8 * NR_CPUS      )
 #define IO_APIC_VECTOR_LIMIT		( 32 * MAX_IO_APICS )
 
 #ifdef CONFIG_X86_IO_APIC
 # ifdef CONFIG_SPARSE_IRQ
+#  define CPU_VECTOR_LIMIT		(64 * NR_CPUS)
 #  define NR_IRQS					\
 	(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ?	\
 		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
 		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
 # else
-#  if NR_CPUS < MAX_IO_APICS
-#   define NR_IRQS 			(NR_VECTORS + 4*CPU_VECTOR_LIMIT)
-#  else
-#   define NR_IRQS			(NR_VECTORS + IO_APIC_VECTOR_LIMIT)
-#  endif
+#  define CPU_VECTOR_LIMIT		(32 * NR_CPUS)
+#  define NR_IRQS					\
+	(CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT ?	\
+		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
+		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
 # endif
 #else /* !CONFIG_X86_IO_APIC: */
 # define NR_IRQS			NR_IRQS_LEGACY
arch/x86/kernel/apic/io_apic.c +1 -1
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
@@ -3840,7 +3840,7 @@ int __init arch_probe_nr_irqs(void)
 	/*
 	 * for MSI and HT dyn irq
 	 */
-	nr += nr_irqs_gsi * 16;
+	nr += nr_irqs_gsi * 48;
 #endif
 	if (nr < nr_irqs)
 		nr_irqs = nr;
#1 lore raw
Quoted 5 lines · Yinghai Lu

have a system with lots of igb and ixgbe, when iov/vf are enabled for them, we hit the limit of 3064.

so try to increase NR_IRQS and nr_irqs to about 8000 and 6000. for that system.

could you please provide before/after .data size analysis, expected dynamic allocation overhead difference (if any), etc. - so that we can see whether there's any (and if yes, how much) cost due to the bumping of the limit.

Also, instead of just upping the limit to a new random limit that works on that testbox, could we put some more thought into how much we want to increase it, and stay at least 2-3 years ahead of the expected hardware curve?

Ingo

author
#2 lore raw

PATCH 1/1 x86: increase NR_IRQS and nr_irqs

have a system with lots of igb and ixgbe, when iov/vf are enabled for them, we hit the limit of 3064.

when system have 20 pcie installed, and one card have 2 functions, and one function need 64 msi-x,
may need 20 * 2 * 64 = 2560 for msi-x
but if iov and vf are enabled
may need 20 * 2 * 64 * 3 = 7680 for msi-x
assume system with 5 ioapic, nr_irqs_gsi will be 120.
NR_CPUS = 512, and nr_cpu_ids = 128
will have NR_IRQS = 256 + 512 * 64 = 33024
will have nr_irqs = 120 + 8 * 128 + 120 * 64 = 8824

when SPARSE_IRQ is not set, there is no increase with data when NR_CPUS=128, and SPARSE_IRQ is set
text data bss dec hex filename
21837444 4216564 12480736 38534744 24bfe58 vmlinux.before
21837442 4216580 12480736 38534758 24bfe66 vmlinux.after
when NR_CPUS=4096, and SPARSE_IRQ is set
text data bss dec hex filename
21878619 5610244 13415392 40904255 270263f vmlinux.before
21878617 5610244 13415392 40904253 270263d vmlinux.after

-v2: update comments to address Ingo's concern

---
 arch/x86/include/asm/irq_vectors.h |   12 ++++++------
 arch/x86/kernel/apic/io_apic.c     |    2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/include/asm/irq_vectors.h +6 -6
Index: linux-2.6/arch/x86/include/asm/irq_vectors.h
===================================================================
@@ -154,21 +154,21 @@ static inline int invalid_vm86_irq(int i
 
 #define NR_IRQS_LEGACY			  16
 
-#define CPU_VECTOR_LIMIT		(  8 * NR_CPUS      )
 #define IO_APIC_VECTOR_LIMIT		( 32 * MAX_IO_APICS )
 
 #ifdef CONFIG_X86_IO_APIC
 # ifdef CONFIG_SPARSE_IRQ
+#  define CPU_VECTOR_LIMIT		(64 * NR_CPUS)
 #  define NR_IRQS					\
 	(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ?	\
 		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
 		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
 # else
-#  if NR_CPUS < MAX_IO_APICS
-#   define NR_IRQS 			(NR_VECTORS + 4*CPU_VECTOR_LIMIT)
-#  else
-#   define NR_IRQS			(NR_VECTORS + IO_APIC_VECTOR_LIMIT)
-#  endif
+#  define CPU_VECTOR_LIMIT		(32 * NR_CPUS)
+#  define NR_IRQS					\
+	(CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT ?	\
+		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
+		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
 # endif
 #else /* !CONFIG_X86_IO_APIC: */
 # define NR_IRQS			NR_IRQS_LEGACY
arch/x86/kernel/apic/io_apic.c +1 -1
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
@@ -3840,7 +3840,7 @@ int __init arch_probe_nr_irqs(void)
 	/*
 	 * for MSI and HT dyn irq
 	 */
-	nr += nr_irqs_gsi * 16;
+	nr += nr_irqs_gsi * 64;
 #endif
 	if (nr < nr_irqs)
 		nr_irqs = nr;
#3 lore raw

[tip:x86/apic] x86: Increase NR_IRQS and nr_irqs

Commit-ID:  9959c888a38b0f25b0e81a480f537d6489348442
Gitweb:     http://git.kernel.org/tip/9959c888a38b0f25b0e81a480f537d6489348442
Author:     Yinghai Lu <[email protected]>
AuthorDate: Mon, 28 Dec 2009 21:08:29 -0800
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 30 Dec 2009 11:55:59 +0100

x86: Increase NR_IRQS and nr_irqs

I have a system with lots of igb and ixgbe, when iov/vf are enabled for them, we hit the limit of 3064.

when system has 20 pcie installed, and one card has 2 functions, and one function needs 64 msi-x,
may need 20 * 2 * 64 = 2560 for msi-x

but if iov and vf are enabled
may need 20 * 2 * 64 * 3 = 7680 for msi-x
assume system with 5 ioapic, nr_irqs_gsi will be 120.

NR_CPUS = 512, and nr_cpu_ids = 128
will have NR_IRQS = 256 + 512 * 64 = 33024 will have nr_irqs = 120 + 8 * 128 + 120 * 64 = 8824

When SPARSE_IRQ is not set, there is no increase with kernel data size.

when NR_CPUS=128, and SPARSE_IRQ is set:
text data bss dec hex filename
21837444 4216564 12480736 38534744 24bfe58 vmlinux.before
21837442 4216580 12480736 38534758 24bfe66 vmlinux.after
when NR_CPUS=4096, and SPARSE_IRQ is set
text data bss dec hex filename
21878619 5610244 13415392 40904255 270263f vmlinux.before
21878617 5610244 13415392 40904253 270263d vmlinux.after

Cc Linus Torvalds <[email protected]>
Cc Andrew Morton <[email protected]>

LKML-Reference: <[email protected]>

---
 arch/x86/include/asm/irq_vectors.h |   12 ++++++------
 arch/x86/kernel/apic/io_apic.c     |    2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/include/asm/irq_vectors.h +6 -6
index 4611f08..3ab43df 100644
@@ -154,21 +154,21 @@ static inline int invalid_vm86_irq(int irq)
 
 #define NR_IRQS_LEGACY			  16
 
-#define CPU_VECTOR_LIMIT		(  8 * NR_CPUS      )
 #define IO_APIC_VECTOR_LIMIT		( 32 * MAX_IO_APICS )
 
 #ifdef CONFIG_X86_IO_APIC
 # ifdef CONFIG_SPARSE_IRQ
+#  define CPU_VECTOR_LIMIT		(64 * NR_CPUS)
 #  define NR_IRQS					\
 	(CPU_VECTOR_LIMIT > IO_APIC_VECTOR_LIMIT ?	\
 		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
 		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
 # else
-#  if NR_CPUS < MAX_IO_APICS
-#   define NR_IRQS 			(NR_VECTORS + 4*CPU_VECTOR_LIMIT)
-#  else
-#   define NR_IRQS			(NR_VECTORS + IO_APIC_VECTOR_LIMIT)
-#  endif
+#  define CPU_VECTOR_LIMIT		(32 * NR_CPUS)
+#  define NR_IRQS					\
+	(CPU_VECTOR_LIMIT < IO_APIC_VECTOR_LIMIT ?	\
+		(NR_VECTORS + CPU_VECTOR_LIMIT)  :	\
+		(NR_VECTORS + IO_APIC_VECTOR_LIMIT))
 # endif
 #else /* !CONFIG_X86_IO_APIC: */
 # define NR_IRQS			NR_IRQS_LEGACY
arch/x86/kernel/apic/io_apic.c +1 -1
index de00c46..d9cd1f1 100644
@@ -3840,7 +3840,7 @@ int __init arch_probe_nr_irqs(void)
 	/*
 	 * for MSI and HT dyn irq
 	 */
-	nr += nr_irqs_gsi * 16;
+	nr += nr_irqs_gsi * 64;
 #endif
 	if (nr < nr_irqs)
 		nr_irqs = nr;
#4 lore raw
In reply to Yinghai Lu
Quoted 23 lines · Yinghai Lu

have a system with lots of igb and ixgbe, when iov/vf are enabled for them, we hit the limit of 3064.

when system have 20 pcie installed, and one card have 2 functions, and one function need 64 msi-x,
 may need 20 * 2 * 64 = 2560 for msi-x
but if iov and vf are enabled
 may need 20 * 2 * 64 * 3 = 7680 for msi-x
assume system with 5 ioapic, nr_irqs_gsi will be 120.
NR_CPUS = 512, and nr_cpu_ids = 128
will have NR_IRQS = 256 + 512 * 64 = 33024
will have nr_irqs = 120 + 8 * 128 + 120 * 64 = 8824

when SPARSE_IRQ is not set, there is no increase with data
when NR_CPUS=128, and SPARSE_IRQ is set
  text            data     bss            dec           hex    filename 21837444        4216564 12480736        38534744        24bfe58 vmlinux.before 21837442        4216580 12480736        38534758        24bfe66 vmlinux.after when NR_CPUS=4096, and SPARSE_IRQ is set
  text            data     bss            dec           hex    filename 21878619        5610244 13415392        40904255        270263f vmlinux.before 21878617        5610244 13415392        40904253        270263d vmlinux.after

Quoted 3 lines

-v2: update comments to address Ingo's concern

I'm not sure this is the best plan, but may be okay for now. What happens when all of your slots have 6 port 82599 ixgbe adapters in them? They are being made[1], as well as quad port 82576 igb adapters, however I'm not fully sure of the SRIOV support of the bridges being used on those adapters.

Is it on the table to (re-)design this subsystem to be a little more dynamic? There are probably examples in ppc64 or ia64 directories. Every time you suggest a limit I can find a case where it won't be enough.

[1] http://www.hotlavasystems.com/products_10gbe.html

author
#5 lore raw
Quoted 34 lines · Jesse Brandeburg
Quoted 23 lines · Yinghai Lu

have a system with lots of igb and ixgbe, when iov/vf are enabled for them, we hit the limit of 3064.

when system have 20 pcie installed, and one card have 2 functions, and one function need 64 msi-x,
may need 20 * 2 * 64 = 2560 for msi-x
but if iov and vf are enabled
may need 20 * 2 * 64 * 3 = 7680 for msi-x
assume system with 5 ioapic, nr_irqs_gsi will be 120.
NR_CPUS = 512, and nr_cpu_ids = 128
will have NR_IRQS = 256 + 512 * 64 = 33024
will have nr_irqs = 120 + 8 * 128 + 120 * 64 = 8824

when SPARSE_IRQ is not set, there is no increase with data when NR_CPUS=128, and SPARSE_IRQ is set

  text            data     bss            dec           hex    filename
21837444        4216564 12480736        38534744        24bfe58 vmlinux.before
21837442        4216580 12480736        38534758        24bfe66 vmlinux.after
when NR_CPUS=4096, and SPARSE_IRQ is set
  text            data     bss            dec           hex    filename
21878619        5610244 13415392        40904255        270263f vmlinux.before
21878617        5610244 13415392        40904253        270263d vmlinux.after
Quoted 3 lines

-v2: update comments to address Ingo's concern

I'm not sure this is the best plan, but may be okay for now. What happens when all of your slots have 6 port 82599 ixgbe adapters in them? They are being made[1], as well as quad port 82576 igb adapters, however I'm not fully sure of the SRIOV support of the bridges being used on those adapters.

Quoted 6 lines

Is it on the table to (re-)design this subsystem to be a little more dynamic? There are probably examples in ppc64 or ia64 directories. Every time you suggest a limit I can find a case where it won't be enough.

[1] http://www.hotlavasystems.com/products_10gbe.html

you mean
20 * 6 * 64 * 3 ?

23040

maybe we can just keep nr_irqs = (256 - 32 - 10) * nr_cpu_ids? 32: for exception
10: for IPI etc.

YH

author
#6 lore raw

Subject: [PATCH 1/2] x86: get back 15 vectors

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

also try to reuse 0x30 to 0x3f after smp_affinity for irq[0,15] is changed to other cpu.

---
 arch/x86/kernel/apic/io_apic.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/kernel/apic/io_apic.c +3 -2
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
@@ -1162,7 +1162,8 @@ __assign_irq_vector(int irq, struct irq_
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	static int current_vector = FIRST_EXTERNAL_VECTOR + 1;
+	static int current_offset = 0;
 	unsigned int old_vector;
 	int cpu, err;
 	cpumask_var_t tmp_mask;
@@ -1198,7 +1199,7 @@ next:
 		if (vector >= first_system_vector) {
 			/* If out of vectors on large boxen, must share them. */
 			offset = (offset + 1) % 8;
-			vector = FIRST_DEVICE_VECTOR + offset;
+			vector = FIRST_EXTERNAL_VECTOR + 1 + offset;
 		}
 		if (unlikely(current_vector == vector))
 			continue;
#7 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Yinghai Lu <[email protected]> writes:

This patch is wrong.

Quoted 3 lines

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

We can not use any of 0x20 - 0x2f for ioapic irqs. We need the entire priority level to ensure that the irq move cleanup ipi is of a lower priority.

Quoted 1 line

also try to reuse 0x30 to 0x3f after smp_affinity for irq[0,15] is changed to other cpu.

There may be a point with 0x30 to 0x3f as I recall when those irqs come through a legacy pic we need to reserve those vectors on all cpus.

Eric

Quoted 30 lines
---
 arch/x86/kernel/apic/io_apic.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================

arch/x86/kernel/apic/io_apic.c +3 -2
@@ -1162,7 +1162,8 @@ __assign_irq_vector(int irq, struct irq_
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	static int current_vector = FIRST_EXTERNAL_VECTOR + 1;
+	static int current_offset = 0;
 	unsigned int old_vector;
 	int cpu, err;
 	cpumask_var_t tmp_mask;
@@ -1198,7 +1199,7 @@ next:
 		if (vector >= first_system_vector) {
 			/* If out of vectors on large boxen, must share them. */
 			offset = (offset + 1) % 8;
-			vector = FIRST_DEVICE_VECTOR + offset;
+			vector = FIRST_EXTERNAL_VECTOR + 1 + offset;
 		}
 		if (unlikely(current_vector == vector))
 			continue;
author
#8 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 8 lines · Eric W. Biederman

Yinghai Lu <[email protected]> writes:

This patch is wrong.

Quoted 3 lines

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

Quoted 8 lines

We can not use any of 0x20 - 0x2f for ioapic irqs. We need the entire priority level to ensure that the irq move cleanup ipi is of a lower priority.

Quoted 1 line

also try to reuse 0x30 to 0x3f after smp_affinity for irq[0,15] is changed to other cpu.

There may be a point with 0x30 to 0x3f as I recall when those irqs come through a legacy pic we need to reserve those vectors on all cpus.

ok, I see.

any reason that we can not use 0x40?

Thanks

Yinghai

#9 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 13 lines · Yinghai Lu
Quoted 12 lines · Eric W. Biederman

Yinghai Lu <[email protected]> writes:

This patch is wrong.

Quoted 3 lines

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

We can not use any of 0x20 - 0x2f for ioapic irqs. We need the entire priority level to ensure that the irq move cleanup ipi is of a lower priority.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

also try to reuse 0x30 to 0x3f after smp_affinity for irq[0,15] is changed to other cpu.

There may be a point with 0x30 to 0x3f as I recall when those irqs come through a legacy pic we need to reserve those vectors on all cpus.

ok, I see.

any reason that we can not use 0x40?

Not that I now of. Reading the comment it looks like it was only skipped so that the initial assignment of vectors would be.

0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1 Instead of.
0x30, 0x40, 0x50, 0x60, 0x70, 0x90, 0xa0, 0xb0, 0xc0, 0xc0, 0xe0

Which doesn't seem to be the worst notion, but at the point we are looking for every vector we can get it does seem to be problematic.

Eric

#10 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 6 lines · Eric W. Biederman
Quoted 2 lines

any reason that we can not use 0x40?

Not that I now of. Reading the comment it looks like it was only skipped so that the initial assignment of vectors would be.

Quoted 7 lines

0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1 Instead of.
0x30, 0x40, 0x50, 0x60, 0x70, 0x90, 0xa0, 0xb0, 0xc0, 0xc0, 0xe0

Which doesn't seem to be the worst notion, but at the point we are looking for every vector we can get it does seem to be problematic.

This can presumably be worked around by tweaking the initial assignment algorithm slightly, without losing a whole vector to that.

Also, if we abuse vector 0x1f as the IRQ reassignment vector, we free up a full 16 vectors per CPU -- this seems worthwhile especially since it is a decision that can be trivially undone in the future: this is all kernel internal, we're not creating any kind of API.

-hpa

#11 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

In reply to Eric W. Biederman
Quoted 4 lines · Eric W. Biederman

Yinghai Lu <[email protected]> writes:

This patch is wrong.

Quoted 8 lines
Quoted 3 lines

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

We can not use any of 0x20 - 0x2f for ioapic irqs. We need the entire priority level to ensure that the irq move cleanup ipi is of a lower priority.

Almost makes one want to abuse 0x1f for that. Although 0x00..0x1f are reserved for exceptions, the APICs range down to 0x10, and well, when 0x1f ends up actually getting used as an exception vector that we support, then we can trivially change that. In the meantime it would actually make use of an otherwise-unusable APIC priority level.

-hpa

#12 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 14 lines · H. Peter Anvin
Quoted 4 lines · Eric W. Biederman

Yinghai Lu <[email protected]> writes:

This patch is wrong.

Quoted 8 lines
Quoted 3 lines

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

We can not use any of 0x20 - 0x2f for ioapic irqs. We need the entire priority level to ensure that the irq move cleanup ipi is of a lower priority.

Quoted 5 lines

Almost makes one want to abuse 0x1f for that. Although 0x00..0x1f are reserved for exceptions, the APICs range down to 0x10, and well, when 0x1f ends up actually getting used as an exception vector that we support, then we can trivially change that. In the meantime it would actually make use of an otherwise-unusable APIC priority level.

An optimization like that (with a big fat comment) seems reasonable to me.

Eric

author
#13 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 16 lines · Eric W. Biederman
Quoted 14 lines · H. Peter Anvin
Quoted 12 lines · Eric W. Biederman

Yinghai Lu <[email protected]> writes:

This patch is wrong.

Quoted 3 lines

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

We can not use any of 0x20 - 0x2f for ioapic irqs. We need the entire priority level to ensure that the irq move cleanup ipi is of a lower priority.

Quoted 8 lines
Quoted 5 lines

Almost makes one want to abuse 0x1f for that. Although 0x00..0x1f are reserved for exceptions, the APICs range down to 0x10, and well, when 0x1f ends up actually getting used as an exception vector that we support, then we can trivially change that. In the meantime it would actually make use of an otherwise-unusable APIC priority level.

An optimization like that (with a big fat comment) seems reasonable to me.

so we can use [0x10, 0x1f]

sth like this?

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x10
according to Eric, we should hold 16 vectors for IRQ MOVE

---
 arch/x86/include/asm/irq_vectors.h |    3 ++-
 arch/x86/kernel/apic/io_apic.c     |    5 +++--
 arch/x86/kernel/irqinit.c          |   11 +++++++++--
 3 files changed, 14 insertions(+), 5 deletions(-)
arch/x86/kernel/apic/io_apic.c +3 -2
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
@@ -1162,7 +1162,8 @@ __assign_irq_vector(int irq, struct irq_
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	static int current_vector = 0;
+	static int current_offset = 0;
 	unsigned int old_vector;
 	int cpu, err;
 	cpumask_var_t tmp_mask;
@@ -1198,7 +1199,7 @@ next:
 		if (vector >= first_system_vector) {
 			/* If out of vectors on large boxen, must share them. */
 			offset = (offset + 1) % 8;
-			vector = FIRST_DEVICE_VECTOR + offset;
+			vector = 0 + offset;
 		}
 		if (unlikely(current_vector == vector))
 			continue;
arch/x86/include/asm/irq_vectors.h +2 -1
Index: linux-2.6/arch/x86/include/asm/irq_vectors.h
===================================================================
@@ -30,8 +30,9 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x10
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x10
 
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
arch/x86/kernel/irqinit.c +9 -2
Index: linux-2.6/arch/x86/kernel/irqinit.c
===================================================================
@@ -149,6 +149,8 @@ static void __init smp_intr_init(void)
 {
 #ifdef CONFIG_SMP
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
+	int i;
+
 	/*
 	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
 	 * IPI, driven by wakeup.
@@ -174,7 +176,9 @@ static void __init smp_intr_init(void)
 
 	/* Low priority IPI to cleanup after moving an irq */
 	set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
-	set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
+	/* Eric said: Need to hold entire priority */
+	for (i = IRQ_MOVE_CLEANUP_VECTOR; i < IRQ_MOVE_CLEANUP_VECTOR+0x10; i++)
+		set_bit(i, used_vectors);
 
 	/* IPI used for rebooting/stopping */
 	alloc_intr_gate(REBOOT_VECTOR, reboot_interrupt);
@@ -222,6 +226,9 @@ void __init native_init_IRQ(void)
 	/* Execute any quirks before the call gates are initialised: */
 	x86_init.irqs.pre_vector_init();
 
+	for (i = 0; i < 0x10; i++)
+		set_bit(i, used_vectors);
+
 	apic_intr_init();
 
 	/*
@@ -229,7 +236,7 @@ void __init native_init_IRQ(void)
 	 * us. (some of these will be overridden and become
 	 * 'special' SMP interrupts)
 	 */
-	for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
+	for (i = 0; i < NR_VECTORS; i++) {
 		/* IA32_SYSCALL_VECTOR could be used in trap_init already. */
 		if (!test_bit(i, used_vectors))
 			set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
#14 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 9 lines · Yinghai Lu

sth like this?

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x10
according to Eric, we should hold 16 vectors for IRQ MOVE

Yinghai we have to change IRQ_MOVE_CLEANUP_VECTOR to 0x1f or so. From the cpu perspective this vector is documented as illegal, so we need to check if this change will work on the cpu's we have today to get some confidence.

thanks,
suresh

#15 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 8 lines · Suresh Siddha
Quoted 7 lines · Yinghai Lu

sth like this?

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x10
according to Eric, we should hold 16 vectors for IRQ MOVE

Quoted 8 lines
Quoted 2 lines

Yinghai we have to change IRQ_MOVE_CLEANUP_VECTOR to 0x1f or so. From the cpu perspective this vector is documented as illegal, so we need to check if this change will work on the cpu's we have today to get some confidence.

It's documented as reserved, not illegal. The ability for the APIC to generate vectors starting at 0x10 is documented, as is the ability for the CPU to receive any vector number as an interrupt -- in fact, the legacy BIOS relies on being able to receive interrupts starting at vector 0x08. It causes problems galore, but only at the software level.

-hpa

#16 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 18 lines · H. Peter Anvin
Quoted 8 lines · Suresh Siddha
Quoted 7 lines · Yinghai Lu

sth like this?

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x10
according to Eric, we should hold 16 vectors for IRQ MOVE

Quoted 8 lines
Quoted 2 lines

Yinghai we have to change IRQ_MOVE_CLEANUP_VECTOR to 0x1f or so. From the cpu perspective this vector is documented as illegal, so we need to check if this change will work on the cpu's we have today to get some confidence.

Quoted 5 lines

It's documented as reserved, not illegal. The ability for the APIC to generate vectors starting at 0x10 is documented, as is the ability for the CPU to receive any vector number as an interrupt -- in fact, the legacy BIOS relies on being able to receive interrupts starting at vector 0x08. It causes problems galore, but only at the software level.

I have checked out couple of platforms (including 32-bit atom) and 0x1f vector logic seems to be working.

Hopefully we won't have other hardware or software issues (vmm restrictions etc) with this logic.

thanks,
suresh

author
#17 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 25 lines · Suresh Siddha
Quoted 18 lines · H. Peter Anvin
Quoted 8 lines · Suresh Siddha
Quoted 7 lines · Yinghai Lu

sth like this?

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x10
according to Eric, we should hold 16 vectors for IRQ MOVE

Quoted 8 lines
Quoted 2 lines

Yinghai we have to change IRQ_MOVE_CLEANUP_VECTOR to 0x1f or so. From the cpu perspective this vector is documented as illegal, so we need to check if this change will work on the cpu's we have today to get some confidence.

Quoted 5 lines

It's documented as reserved, not illegal. The ability for the APIC to generate vectors starting at 0x10 is documented, as is the ability for the CPU to receive any vector number as an interrupt -- in fact, the legacy BIOS relies on being able to receive interrupts starting at vector 0x08. It causes problems galore, but only at the software level.

Quoted 6 lines

I have checked out couple of platforms (including 32-bit atom) and 0x1f vector logic seems to be working.

Hopefully we won't have other hardware or software issues (vmm restrictions etc) with this logic.

good. hope it is final version. let's have hpa own it.

From: "H. Peter Anvin" <[email protected]>
Subject: [PATCH] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x1f -v3: update comments from Eric
-v4: update comments from hpa
-v5: use round up for IRQ0_VECTOR according to hpa

---
 arch/x86/include/asm/irq_vectors.h |   40 ++++++++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 14 deletions(-)
arch/x86/include/asm/irq_vectors.h +19 -7
Index: linux-2.6/arch/x86/include/asm/irq_vectors.h
===================================================================
@@ -30,26 +30,38 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f.
+ *   0x1f is documented as reserved.  However, the ability for the APIC
+ *   to generate vectors starting at 0x10 is documented, as is the
+ *   ability for the CPU to receive any vector number as an interrupt.
+ *   0x1f is used for IRQ_MOVE_CLEANUP_VECTOR since that vector needs
+ *   an entire privilege level (16 vectors) all by itself at a higher
+ *   priority than any actual device vector.  Thus, by placing it in the
+ *   otherwise-unusable 0x10 privilege level, we avoid wasting a full
+ *   16-vector block.
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 
+#define IA32_SYSCALL_VECTOR		0x80
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
-# define IA32_SYSCALL_VECTOR		0x80
-#else
-# define IA32_SYSCALL_VECTOR		0x80
 #endif
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * Reserve the lowest usable priority level 0x10 - 0x1f for triggering
  * cleanup after irq migration.
+ * this overlaps with the reserved range for cpu exceptions so this
+ * will need to be changed to 0x20 - 0x2f if the last cpu exception is
+ * ever allocated.
  */
+
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
 /*
- * Vectors 0x30-0x3f are used for ISA interrupts.
+ * Vectors 0x20-0x2f are used for ISA interrupts.
+ *   round up to the next 16-vector boundary
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			((FIRST_EXTERNAL_VECTOR + 16) & ~15)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)
#18 lore raw

[tip:x86/apic] x86, apic: Reclaim IDT vectors 0x20-0x2f

Commit-ID:  99d113b17e8ca5a8b68a9d3f7691e2f552dd6a06
Gitweb:     http://git.kernel.org/tip/99d113b17e8ca5a8b68a9d3f7691e2f552dd6a06
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Mon, 4 Jan 2010 16:16:06 -0800
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Mon, 4 Jan 2010 21:12:52 -0800

x86, apic: Reclaim IDT vectors 0x20-0x2f

Reclaim 16 IDT vectors and make them available for general allocation.

Reclaim vectors 0x20-0x2f by reallocating the IRQ_MOVE_CLEANUP_VECTOR to vector 0x1f. This is in the range of vector numbers that is officially reserved for the CPU (for exceptions), however, the use of the APIC to generate any vector 0x10 or above is documented, and the CPU internally can receive any vector number (the legacy BIOS uses INT 0x08-0x0f for interrupts, as messed up as that is.)

Since IRQ_MOVE_CLEANUP_VECTOR has to be alone in the lowest-numbered priority level (block of 16), this effectively enables us to reclaim an otherwise-unusable APIC priority level and put it to use.

Since this is a transient kernel-only allocation we can change it at any time, and if/when there is an exception at vector 0x1f this assignment needs to be changed as part of OS enabling that new feature.

LKML-Reference: <[email protected]>

---
 arch/x86/include/asm/irq_vectors.h |   28 ++++++++++++++++++++--------
 1 files changed, 20 insertions(+), 8 deletions(-)
arch/x86/include/asm/irq_vectors.h +20 -8
index 3ab43df..dbc81ac 100644
@@ -30,26 +30,38 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f.
+ *   0x1f is documented as reserved.  However, the ability for the APIC
+ *   to generate vectors starting at 0x10 is documented, as is the
+ *   ability for the CPU to receive any vector number as an interrupt.
+ *   0x1f is used for IRQ_MOVE_CLEANUP_VECTOR since that vector needs
+ *   an entire privilege level (16 vectors) all by itself at a higher
+ *   priority than any actual device vector.  Thus, by placing it in the
+ *   otherwise-unusable 0x10 privilege level, we avoid wasting a full
+ *   16-vector block.
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 
+#define IA32_SYSCALL_VECTOR		0x80
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
-# define IA32_SYSCALL_VECTOR		0x80
-#else
-# define IA32_SYSCALL_VECTOR		0x80
 #endif
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * Reserve the lowest usable priority level 0x10 - 0x1f for triggering
  * cleanup after irq migration.
+ * this overlaps with the reserved range for cpu exceptions so this
+ * will need to be changed to 0x20 - 0x2f if the last cpu exception is
+ * ever allocated.
  */
+
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
 /*
- * Vectors 0x30-0x3f are used for ISA interrupts.
+ * Vectors 0x20-0x2f are used for ISA interrupts.
+ *   round up to the next 16-vector boundary
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			((FIRST_EXTERNAL_VECTOR + 16) & ~15)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)
@@ -122,7 +134,7 @@
 
 /*
  * First APIC vector available to drivers: (vectors 0x30-0xee) we
- * start at 0x31(0x41) to spread out vectors evenly between priority
+ * start at 0x31 to spread out vectors evenly between priority
  * levels. (0x80 is the syscall vector)
  */
 #define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
#19 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

In reply to Yinghai Lu

[Adding Suresh to the Cc: list]

Quoted 5 lines · Yinghai Lu

so we can use [0x10, 0x1f]

sth like this?

No!!!

[0x10, 0x1f] is reserved for exceptions. We can probably get away with stealing *one* vector... presumably at the end (0x1f). However, we can absolutely not use the whole block: 0x10-0x13 is occupied by exceptions we already have OS support for (#MF, #AC, #MC, and #XM), and it's pretty much guaranteed we'll have more coming. However, growth is quite slow and since this is a kernel-internal vector (not accessible to user space) it is not creating an API.

In other words, we could change FIRST_EXTERNAL_VECTOR to 0x1f, and use it for IRQ_MOVE_CLEANUP_VECTOR. Then use 0x20..0x2f for the legacy vectors.

-hpa

author
#20 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 19 lines · H. Peter Anvin

[Adding Suresh to the Cc: list]

Quoted 5 lines · Yinghai Lu

so we can use [0x10, 0x1f]

sth like this?

No!!!

[0x10, 0x1f] is reserved for exceptions. We can probably get away with stealing *one* vector... presumably at the end (0x1f). However, we can absolutely not use the whole block: 0x10-0x13 is occupied by exceptions we already have OS support for (#MF, #AC, #MC, and #XM), and it's pretty much guaranteed we'll have more coming. However, growth is quite slow and since this is a kernel-internal vector (not accessible to user space) it is not creating an API.

Quoted 3 lines

In other words, we could change FIRST_EXTERNAL_VECTOR to 0x1f, and use it for IRQ_MOVE_CLEANUP_VECTOR. Then use 0x20..0x2f for the legacy vectors.

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x1f

---
 arch/x86/include/asm/irq_vectors.h |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
arch/x86/include/asm/irq_vectors.h +5 -4
Index: linux-2.6/arch/x86/include/asm/irq_vectors.h
===================================================================
@@ -30,8 +30,9 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
@@ -41,15 +42,15 @@
 #endif
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * Reserve the lowest usable priority level 0x1f for triggering
  * cleanup after irq migration.
  */
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
 /*
- * Vectors 0x30-0x3f are used for ISA interrupts.
+ * Vectors 0x20-0x2f are used for ISA interrupts.
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 1)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)
#21 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 20 lines · Yinghai Lu
Quoted 19 lines · H. Peter Anvin

[Adding Suresh to the Cc: list]

Quoted 5 lines · Yinghai Lu

so we can use [0x10, 0x1f]

sth like this?

No!!!

[0x10, 0x1f] is reserved for exceptions. We can probably get away with stealing *one* vector... presumably at the end (0x1f). However, we can absolutely not use the whole block: 0x10-0x13 is occupied by exceptions we already have OS support for (#MF, #AC, #MC, and #XM), and it's pretty much guaranteed we'll have more coming. However, growth is quite slow and since this is a kernel-internal vector (not accessible to user space) it is not creating an API.

Quoted 6 lines
Quoted 3 lines

In other words, we could change FIRST_EXTERNAL_VECTOR to 0x1f, and use it for IRQ_MOVE_CLEANUP_VECTOR. Then use 0x20..0x2f for the legacy vectors.

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x1f

The code in the patch is ok, but the comments are wrong.

Quoted 12 lines
---
 arch/x86/include/asm/irq_vectors.h |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

Index: linux-2.6/arch/x86/include/asm/irq_vectors.h
===================================================================

arch/x86/include/asm/irq_vectors.h line 33

Quoted 4 lines
arch/x86/include/asm/irq_vectors.h +1 -0
@@ -30,8 +30,9 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f

You need to document the reasons here.

arch/x86/include/asm/irq_vectors.h line 45

Quoted 12 lines
arch/x86/include/asm/irq_vectors.h +2 -2
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
@@ -41,15 +42,15 @@
 #endif
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * Reserve the lowest usable priority level 0x1f for triggering

Should be:
+ * Reserve the lowest usable priority level 0x10 - 0x1f for triggering

arch/x86/include/asm/irq_vectors.h line 46

Quoted 1 line
arch/x86/include/asm/irq_vectors.h +0 -0
  * cleanup after irq migration.
+   * this overlaps with the reserved range for cpu exceptions so this
+   * will need to be changed to 0x20 - 0x2f if the last cpu exception is
+   * ever allocated.
>   */
Quoted 11 lines
arch/x86/include/asm/irq_vectors.h +2 -2
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
 /*
- * Vectors 0x30-0x3f are used for ISA interrupts.
+ * Vectors 0x20-0x2f are used for ISA interrupts.
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 1)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)
author
#22 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x1f -v3: update comments

---
 arch/x86/include/asm/irq_vectors.h |   30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)
arch/x86/include/asm/irq_vectors.h +19 -11
Index: linux-2.6/arch/x86/include/asm/irq_vectors.h
===================================================================
@@ -30,8 +30,12 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f.
+ *   0x1f is documented as reserved. The ability for the APIC to
+ *   generate vectors starting at 0x10 is documented, as is the ability for
+ *   the CPU to receive any vector number as an interrupt
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
@@ -41,15 +45,19 @@
 #endif
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * Reserve the lowest usable priority level 0x10 - 0x1f for triggering
  * cleanup after irq migration.
+ * this overlaps with the reserved range for cpu exceptions so this
+ * will need to be changed to 0x20 - 0x2f if the last cpu exception is
+ * ever allocated.
  */
+
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
 /*
- * Vectors 0x30-0x3f are used for ISA interrupts.
+ * Vectors 0x20-0x2f are used for ISA interrupts.
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 1)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)
@@ -68,6 +76,13 @@
 #define IRQ15_VECTOR			(IRQ0_VECTOR + 15)
 
 /*
+ * First APIC vector available to drivers: (vectors 0x30-0xee) we
+ * start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */
+#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
+
+/*
  * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
  *
  *  some of the following vectors are 'rare', they are merged
@@ -120,13 +135,6 @@
  */
 #define MCE_SELF_VECTOR			0xeb
 
-/*
- * First APIC vector available to drivers: (vectors 0x30-0xee) we
- * start at 0x31(0x41) to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
- */
-#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
-
 #define NR_VECTORS			 256
 
 #define FPU_IRQ				  13
#23 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 4 lines · Yinghai Lu
arch/x86/include/asm/irq_vectors.h +0 -0
@@ -30,8 +30,12 @@
 /*

arch/x86/include/asm/irq_vectors.h line 39

Quoted 10 lines
arch/x86/include/asm/irq_vectors.h +5 -1
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f.
+ *   0x1f is documented as reserved. The ability for the APIC to
+ *   generate vectors starting at 0x10 is documented, as is the ability for
+ *   the CPU to receive any vector number as an interrupt
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 

This really isn't a sufficient explanation either. I know writing English prose is very difficult for you, but I'm sorry, you really need to start getting better about your comments and commit messages.

In this case, the text is missing one very important piece of the
justification: otherwise we have to waste a full 16 vectors in order for the IRQ migration interrupt to get its own priority level. Thus, something like this:

*   0x1f is documented as reserved.  However, the ability for the APIC
*   to generate vectors starting at 0x10 is documented, as is the
*   ability for the CPU to receive any vector number as an interrupt.
*   0x1f is used for IRQ_MOVE_CLEANUP_VECTOR since that vector needs
*   an entire privilege level (16 vectors) all by itself at a higher
*   priority than any actual device vector.  Thus, by placing it in the
*   otherwise-unusable 0x10 privilege level, we avoid wasting a full
*   16-vector block.

-hpa

author
#24 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 8 lines · H. Peter Anvin
*   0x1f is documented as reserved.  However, the ability for the APIC
*   to generate vectors starting at 0x10 is documented, as is the
*   ability for the CPU to receive any vector number as an interrupt.
*   0x1f is used for IRQ_MOVE_CLEANUP_VECTOR since that vector needs
*   an entire privilege level (16 vectors) all by itself at a higher
*   priority than any actual device vector.  Thus, by placing it in the
*   otherwise-unusable 0x10 privilege level, we avoid wasting a full
*   16-vector block.

Subject: [PATCH 1/2] x86: get back 16 vectors

-v2: according to hpa that we could start from 0x1f -v3: update comments from Eric
-v4: update comments from hpa

---
 arch/x86/include/asm/irq_vectors.h |   35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)
arch/x86/include/asm/irq_vectors.h +24 -11
Index: linux-2.6/arch/x86/include/asm/irq_vectors.h
===================================================================
@@ -30,8 +30,17 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f.
+ *   0x1f is documented as reserved.  However, the ability for the APIC
+ *   to generate vectors starting at 0x10 is documented, as is the
+ *   ability for the CPU to receive any vector number as an interrupt.
+ *   0x1f is used for IRQ_MOVE_CLEANUP_VECTOR since that vector needs
+ *   an entire privilege level (16 vectors) all by itself at a higher
+ *   priority than any actual device vector.  Thus, by placing it in the
+ *   otherwise-unusable 0x10 privilege level, we avoid wasting a full
+ *   16-vector block.
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
@@ -41,15 +50,19 @@
 #endif
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * Reserve the lowest usable priority level 0x10 - 0x1f for triggering
  * cleanup after irq migration.
+ * this overlaps with the reserved range for cpu exceptions so this
+ * will need to be changed to 0x20 - 0x2f if the last cpu exception is
+ * ever allocated.
  */
+
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
 /*
- * Vectors 0x30-0x3f are used for ISA interrupts.
+ * Vectors 0x20-0x2f are used for ISA interrupts.
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 1)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)
@@ -68,6 +81,13 @@
 #define IRQ15_VECTOR			(IRQ0_VECTOR + 15)
 
 /*
+ * First APIC vector available to drivers: (vectors 0x30-0xee) we
+ * start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */
+#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
+
+/*
  * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
  *
  *  some of the following vectors are 'rare', they are merged
@@ -120,13 +140,6 @@
  */
 #define MCE_SELF_VECTOR			0xeb
 
-/*
- * First APIC vector available to drivers: (vectors 0x30-0xee) we
- * start at 0x31(0x41) to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
- */
-#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
-
 #define NR_VECTORS			 256
 
 #define FPU_IRQ				  13
#25 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 45 lines · Yinghai Lu
arch/x86/include/asm/irq_vectors.h +17 -4
@@ -30,8 +30,17 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f.
+ *   0x1f is documented as reserved.  However, the ability for the APIC
+ *   to generate vectors starting at 0x10 is documented, as is the
+ *   ability for the CPU to receive any vector number as an interrupt.
+ *   0x1f is used for IRQ_MOVE_CLEANUP_VECTOR since that vector needs
+ *   an entire privilege level (16 vectors) all by itself at a higher
+ *   priority than any actual device vector.  Thus, by placing it in the
+ *   otherwise-unusable 0x10 privilege level, we avoid wasting a full
+ *   16-vector block.
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
@@ -41,15 +50,19 @@
 #endif
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * Reserve the lowest usable priority level 0x10 - 0x1f for triggering
  * cleanup after irq migration.
+ * this overlaps with the reserved range for cpu exceptions so this
+ * will need to be changed to 0x20 - 0x2f if the last cpu exception is
+ * ever allocated.
  */
+
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
 /*
- * Vectors 0x30-0x3f are used for ISA interrupts.
+ * Vectors 0x20-0x2f are used for ISA interrupts.
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 1)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)

arch/x86/include/asm/irq_vectors.h line 82

Quoted 2 lines
arch/x86/include/asm/irq_vectors.h +0 -0
@@ -68,6 +81,13 @@
 #define IRQ15_VECTOR			(IRQ0_VECTOR + 15)
 

I'm not sure that making IRQ_MOVE_CLEANUP_VECTOR and IRQ0_VECTOR offsets from FIRST_EXTERNAL_VECTOR makes sense from a readability perspective. These are now magic numbers, and making them offsets is only confusing, as it implies we could do it differently.

If nothing else, the actual logic for IRQ0_VECTOR should be:

#define IRQ0_VECTOR ((FIRST_EXTERNAL_VECTOR + 16) & ~15)

... since that is what we actually want -- we round up to the next 16-vector boundary. Both +16 and +1 misrepresent the logic.

arch/x86/include/asm/irq_vectors.h line 89

Quoted 7 lines
arch/x86/include/asm/irq_vectors.h +6 -0
 /*
+ * First APIC vector available to drivers: (vectors 0x30-0xee) we
+ * start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */
+#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
+

We really should fix that so we can do +1 here instead of +2; that presumably means fixing the logic so we do something smarter than just jump over 0x80.

-hpa

author
#26 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 54 lines · H. Peter Anvin
Quoted 45 lines · Yinghai Lu
arch/x86/include/asm/irq_vectors.h +17 -4
@@ -30,8 +30,17 @@
 /*
  * IDT vectors usable for external interrupt sources start
  * at 0x20:
+ * hpa said we can start from 0x1f.
+ *   0x1f is documented as reserved.  However, the ability for the APIC
+ *   to generate vectors starting at 0x10 is documented, as is the
+ *   ability for the CPU to receive any vector number as an interrupt.
+ *   0x1f is used for IRQ_MOVE_CLEANUP_VECTOR since that vector needs
+ *   an entire privilege level (16 vectors) all by itself at a higher
+ *   priority than any actual device vector.  Thus, by placing it in the
+ *   otherwise-unusable 0x10 privilege level, we avoid wasting a full
+ *   16-vector block.
  */
-#define FIRST_EXTERNAL_VECTOR		0x20
+#define FIRST_EXTERNAL_VECTOR		0x1f
 
 #ifdef CONFIG_X86_32
 # define SYSCALL_VECTOR			0x80
@@ -41,15 +50,19 @@
 #endif
 
 /*
- * Reserve the lowest usable priority level 0x20 - 0x2f for triggering
+ * Reserve the lowest usable priority level 0x10 - 0x1f for triggering
  * cleanup after irq migration.
+ * this overlaps with the reserved range for cpu exceptions so this
+ * will need to be changed to 0x20 - 0x2f if the last cpu exception is
+ * ever allocated.
  */
+
 #define IRQ_MOVE_CLEANUP_VECTOR		FIRST_EXTERNAL_VECTOR
 
 /*
- * Vectors 0x30-0x3f are used for ISA interrupts.
+ * Vectors 0x20-0x2f are used for ISA interrupts.
  */
-#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 0x10)
+#define IRQ0_VECTOR			(FIRST_EXTERNAL_VECTOR + 1)
 
 #define IRQ1_VECTOR			(IRQ0_VECTOR +  1)
 #define IRQ2_VECTOR			(IRQ0_VECTOR +  2)

arch/x86/include/asm/irq_vectors.h line 82

Quoted 2 lines
arch/x86/include/asm/irq_vectors.h +0 -0
@@ -68,6 +81,13 @@
 #define IRQ15_VECTOR			(IRQ0_VECTOR + 15)
 

I'm not sure that making IRQ_MOVE_CLEANUP_VECTOR and IRQ0_VECTOR offsets from FIRST_EXTERNAL_VECTOR makes sense from a readability perspective. These are now magic numbers, and making them offsets is only confusing, as it implies we could do it differently.

Quoted 6 lines

If nothing else, the actual logic for IRQ0_VECTOR should be:

#define IRQ0_VECTOR ((FIRST_EXTERNAL_VECTOR + 16) & ~15)

... since that is what we actually want -- we round up to the next 16-vector boundary. Both +16 and +1 misrepresent the logic.

that will be good, if later update FIRST_EXTERNAL_VECTOR...

Quoted 12 lines

arch/x86/include/asm/irq_vectors.h line 89

Quoted 8 lines
arch/x86/include/asm/irq_vectors.h +6 -0
 /*
+ * First APIC vector available to drivers: (vectors 0x30-0xee) we
+ * start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */
+#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
+

We really should fix that so we can do +1 here instead of +2; that presumably means fixing the logic so we do something smarter than just jump over 0x80.

we already use used_vectors to skip 0x80. so we could change that to +1?

YH

#27 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 13 lines · Yinghai Lu
Quoted 12 lines

Review

Quoted 8 lines

/*
+ * First APIC vector available to drivers: (vectors 0x30-0xee) we
+ * start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */

(quoted diff) +2 -0
+#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
+

We really should fix that so we can do +1 here instead of +2; that presumably means fixing the logic so we do something smarter than just jump over 0x80.

Quoted 2 lines

we already use used_vectors to skip 0x80. so we could change that to +1?

Yes, but the problem is that we *skip* 0x80, which leads to suboptimal allocation on systems with only a handful of vectors.

The easy solution to accomplishing what we want without wasting vector 0x30 is obviously to start allocation at 0x31, but not by artificially limiting the vector space; see the attached patch.

For what it's worth, this code(__assign_irq_vector() in arch/x86/kernel/apic/io_apic.c) has me somewhat confused about the use of the constant 8:

		vector += 8;

The only justification that I can immediately think of is to try to assign exactly two sources to each priority level (since early APICs started losing interrupts with more than two sources per priority level.)

This is ancient code -- predates not just the git but the bk history -- and as such I would assume that that is the motivation.

-hpa

Quoted 1 line

From 6e586d7d1da44360b16d2c0ac2bea623c1fcfa6e Mon Sep 17 00:00:00 2001

From: H. Peter Anvin <[email protected]>
Date: Mon, 4 Jan 2010 15:00:57 -0800
Subject: [PATCH] x86, irq: Don't waste a vector to improve vector spread

We want to use a vector-assignment sequence that avoids stumbling onto 0x80 earlier in the sequence, in order to improve the spread of vectors across priority levels on machines with a small number of interrupt sources. Right now, this is done by simply making the first vector (0x31 or 0x41) completely unusable. This is unnecessary; all we need is to start assignment at a +1 offset, we don't actually need to prohibit the usage of this vector once we have wrapped around.

---
 arch/x86/include/asm/irq_vectors.h |    9 +++++----
 arch/x86/kernel/apic/io_apic.c     |    3 ++-
 2 files changed, 7 insertions(+), 5 deletions(-)
arch/x86/include/asm/irq_vectors.h +5 -4
index 4611f08..718dcdd 100644
@@ -121,11 +121,12 @@
 #define MCE_SELF_VECTOR			0xeb
 
 /*
- * First APIC vector available to drivers: (vectors 0x30-0xee) we
- * start at 0x31(0x41) to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
+ * First APIC vector available to drivers: (vectors 0x30-0xee).  We
+ * start allocating at 0x31(0x41) to spread out vectors evenly between
+ * priority levels. (0x80 is the syscall vector)
  */
-#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
+#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 1)
+#define VECTOR_OFFSET_START		1
 
 #define NR_VECTORS			 256
 
arch/x86/kernel/apic/io_apic.c +2 -1
index de00c46..e289148 100644
@@ -1162,7 +1162,8 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	static int current_vector = FIRST_DEVICE_VECTOR + VECTOR_OFFSET_START;
+	static int current_offset = VECTOR_OFFSET_START % 8;
 	unsigned int old_vector;
 	int cpu, err;
 	cpumask_var_t tmp_mask;
Signature · 1 line
1.6.5.2
author
#28 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 28 lines · H. Peter Anvin
Quoted 13 lines · Yinghai Lu
Quoted 12 lines

Review

Quoted 8 lines

/*
+ * First APIC vector available to drivers: (vectors 0x30-0xee) we
+ * start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
+ */

(quoted diff) +2 -0
+#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
+

We really should fix that so we can do +1 here instead of +2; that presumably means fixing the logic so we do something smarter than just jump over 0x80.

Quoted 2 lines

we already use used_vectors to skip 0x80. so we could change that to +1?

Yes, but the problem is that we *skip* 0x80, which leads to suboptimal allocation on systems with only a handful of vectors.

The easy solution to accomplishing what we want without wasting vector 0x30 is obviously to start allocation at 0x31, but not by artificially limiting the vector space; see the attached patch.

For what it's worth, this code(__assign_irq_vector() in arch/x86/kernel/apic/io_apic.c) has me somewhat confused about the use of the constant 8:

Quoted 8 lines
		vector += 8;

The only justification that I can immediately think of is to try to assign exactly two sources to each priority level (since early APICs started losing interrupts with more than two sources per priority level.)

This is ancient code -- predates not just the git but the bk history -- and as such I would assume that that is the motivation.

yes the patch get back 0x30, 0x38, 0x40, 0x48 etc back.

YH

#29 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 3 lines · Yinghai Lu

yes the patch get back 0x30, 0x38, 0x40, 0x48 etc back.

I would have expected the old code to still have had 0x38, 0x40, 0x48, ... available, just missing the first one?

-hpa

author
#30 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 8 lines · H. Peter Anvin
Quoted 3 lines · Yinghai Lu

yes the patch get back 0x30, 0x38, 0x40, 0x48 etc back.

I would have expected the old code to still have had 0x38, 0x40, 0x48, ... available, just missing the first one?

you are right. other via offset=7 to be used.

YH

#32 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

Quoted 4 lines · Yinghai Lu

why not start from 0x30, 0x38, 0x40, 0x48 ...
instead of 0x31, 0x39, 0x41, 0x47...?

YH

The whole point is to defer the skip over 0x80.

-hpa

#33 lore raw

[tip:x86/apic] x86, apic: Don't waste a vector to improve vector spread

In reply to Yinghai Lu
Commit-ID:  ea94396629a3e0cb9a3a9c75335b1de255b30426
Gitweb:     http://git.kernel.org/tip/ea94396629a3e0cb9a3a9c75335b1de255b30426
Author:     H. Peter Anvin <[email protected]>
AuthorDate: Mon, 4 Jan 2010 21:14:41 -0800
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Mon, 4 Jan 2010 21:28:24 -0800

x86, apic: Don't waste a vector to improve vector spread

We want to use a vector-assignment sequence that avoids stumbling onto 0x80 earlier in the sequence, in order to improve the spread of vectors across priority levels on machines with a small number of interrupt sources. Right now, this is done by simply making the first vector (0x31 or 0x41) completely unusable. This is unnecessary; all we need is to start assignment at a +1 offset, we don't actually need to prohibit the usage of this vector once we have wrapped around.

LKML-Reference: <[email protected]>

---
 arch/x86/include/asm/irq_vectors.h |    9 +++++----
 arch/x86/kernel/apic/io_apic.c     |    3 ++-
 2 files changed, 7 insertions(+), 5 deletions(-)
arch/x86/include/asm/irq_vectors.h +5 -4
index dbc81ac..585a428 100644
@@ -133,11 +133,12 @@
 #define MCE_SELF_VECTOR			0xeb
 
 /*
- * First APIC vector available to drivers: (vectors 0x30-0xee) we
- * start at 0x31 to spread out vectors evenly between priority
- * levels. (0x80 is the syscall vector)
+ * First APIC vector available to drivers: (vectors 0x30-0xee).  We
+ * start allocating at 0x31 to spread out vectors evenly between
+ * priority levels. (0x80 is the syscall vector)
  */
-#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 2)
+#define FIRST_DEVICE_VECTOR		(IRQ15_VECTOR + 1)
+#define VECTOR_OFFSET_START		1
 
 #define NR_VECTORS			 256
 
arch/x86/kernel/apic/io_apic.c +2 -1
index d9cd1f1..e9ba090 100644
@@ -1162,7 +1162,8 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	static int current_vector = FIRST_DEVICE_VECTOR + VECTOR_OFFSET_START;
+	static int current_offset = VECTOR_OFFSET_START % 8;
 	unsigned int old_vector;
 	int cpu, err;
 	cpumask_var_t tmp_mask;
#34 lore raw

Re: Subject: [PATCH 1/2] x86: get back 15 vectors

In reply to Yinghai Lu
Quoted 23 lines · Yinghai Lu
Quoted 22 lines · Eric W. Biederman
Quoted 19 lines · H. Peter Anvin
Quoted 4 lines · Eric W. Biederman

Yinghai Lu <[email protected]> writes:

This patch is wrong.

Quoted 8 lines
Quoted 3 lines

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

We can not use any of 0x20 - 0x2f for ioapic irqs. We need the entire priority level to ensure that the irq move cleanup ipi is of a lower priority.

Almost makes one want to abuse 0x1f for that. Although 0x00..0x1f are reserved for exceptions, the APICs range down to 0x10, and well, when 0x1f ends up actually getting used as an exception vector that we support, then we can trivially change that. In the meantime it would actually make use of an otherwise-unusable APIC priority level.

Quoted 6 lines
Quoted 2 lines

An optimization like that (with a big fat comment) seems reasonable to me.

so we can use [0x10, 0x1f]

sth like this?

Something. We can not use all of 0x10 - 0x1f, it is simply that hardware can address all of that. 0x10 is already defined
as something I forget what. 0x12 is already the MCE_VECTOR.

Since hardware has not yet defined 0x1f (and is not likely to for a while. We can use that). So we wind up using hardware priority a single ipi, and hardware exceptions.

Eric

author
#35 lore raw

PATCH 1/2 x86: get back 15 vectors

In reply to Yinghai Lu

between FIRST_EXTERNAL_VECTOR (0x20) and FIRST_DEVICE_VECTOR (0x41)

for 0x20 and 0x2f, we are safe be used_vectors will prevent it to use used one.

also try to reuse 0x30 to 0x3f after smp_affinity for irq[0,15] is changed to other cpu.

---
 arch/x86/kernel/apic/io_apic.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/kernel/apic/io_apic.c +3 -2
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
@@ -1162,7 +1162,8 @@ __assign_irq_vector(int irq, struct irq_
 	 * Also, we've got to be careful not to trash gate
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
-	static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
+	static int current_vector = FIRST_EXTERNAL_VECTOR + 1;
+	static int current_offset = 0;
 	unsigned int old_vector;
 	int cpu, err;
 	cpumask_var_t tmp_mask;
@@ -1198,7 +1199,7 @@ next:
 		if (vector >= first_system_vector) {
 			/* If out of vectors on large boxen, must share them. */
 			offset = (offset + 1) % 8;
-			vector = FIRST_DEVICE_VECTOR + offset;
+			vector = FIRST_EXTERNAL_VECTOR + 1 + offset;
 		}
 		if (unlikely(current_vector == vector))
 			continue;
author
#36 lore raw

PATCH 2/2 x86: get more exact nr_irqs

In reply to Yinghai Lu

first check with NR_VECTORS - FIRST_EXTERNAL_VECTOR - 0x20 aka minus exceptions and system vectors.

NR_CPUS = 512, and nr_cpu_ids = 128
will have NR_IRQS = 256 + 512 * 64 = 33024

assume we have 20 intel ixgbe 6 port cards (with sriov and ixgbevf)

	20 * 6 * 64 * 3 = 23040

first will get:

	128 * (256 - 64) = 24576
then with nr_irqs_gsi will get
	(120 + 8 * 128 + 120 * 256) = 31864

so 24576 will be used for nr_irqs.

24576 * 8 = 196608 bytes will be used for irq_desc_ptrs[]

before this patch:

    have nr_irqs = 120 + 8 * 128 + 120 * 64 = 8824
	and irq_desc_ptrs[] is 70592
---
 arch/x86/kernel/apic/io_apic.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
arch/x86/kernel/apic/io_apic.c +8 -3
Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================
@@ -3833,15 +3833,20 @@ int __init arch_probe_nr_irqs(void)
 {
 	int nr;
 
-	if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
-		nr_irqs = NR_VECTORS * nr_cpu_ids;
+	/* 0x20 for ipi etc system vectors */
+	nr = NR_VECTORS - FIRST_EXTERNAL_VECTOR - 0x20;
+
+	nr *= nr_cpu_ids;
+
+	if (nr < nr_irqs)
+		nr_irqs = nr;
 
 	nr = nr_irqs_gsi + 8 * nr_cpu_ids;
 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
 	/*
 	 * for MSI and HT dyn irq
 	 */
-	nr += nr_irqs_gsi * 64;
+	nr += nr_irqs_gsi * 256;
 #endif
 	if (nr < nr_irqs)
 		nr_irqs = nr;
#37 lore raw

Re: [PATCH 2/2] x86: get more exact nr_irqs

Quoted 16 lines · Yinghai Lu

first check with NR_VECTORS - FIRST_EXTERNAL_VECTOR - 0x20 aka minus exceptions and system vectors.

NR_CPUS = 512, and nr_cpu_ids = 128
will have NR_IRQS = 256 + 512 * 64 = 33024

assume we have 20 intel ixgbe 6 port cards (with sriov and ixgbevf)

	20 * 6 * 64 * 3 = 23040

first will get:

	128 * (256 - 64) = 24576
then with nr_irqs_gsi will get
	(120 + 8 * 128 + 120 * 256) = 31864

so 24576 will be used for nr_irqs.

Quoted 7 lines

24576 * 8 = 196608 bytes will be used for irq_desc_ptrs[]

before this patch:

    have nr_irqs = 120 + 8 * 128 + 120 * 64 = 8824
	and irq_desc_ptrs[] is 70592

I am lost. arch_probe_nr_irqs appears to be total nonsense.

We have three concepts.
- The number of irq sources we can talk about. ( nr_irqs)
- The number of irqs we can possibly service. ((NR_VECTORS - 0x30) *nr_cpu_ids)
- The number of irqs we actually connected up to cards in the system that we need to do something with.

Why do we need to allocate arrays at all?

arch_probe_nr_irqs looks like a pile of magic numbers (even more magic with the addition of 0x20), that is always going to be a little bit wrong.

We should be able to remove the arrays all together and allocate irq_desc dynamically.

Quoted 9 lines
---
 arch/x86/kernel/apic/io_apic.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

Index: linux-2.6/arch/x86/kernel/apic/io_apic.c
===================================================================

arch/x86/kernel/apic/io_apic.c int __init arch_probe_nr_irqs(void) · line 3837

Quoted 7 lines
arch/x86/kernel/apic/io_apic.c +2 -2
@@ -3833,15 +3833,20 @@ int __init arch_probe_nr_irqs(void)
 {
 	int nr;
 
-	if (nr_irqs > (NR_VECTORS * nr_cpu_ids))
-		nr_irqs = NR_VECTORS * nr_cpu_ids;
+	/* 0x20 for ipi etc system vectors */
+	nr = NR_VECTORS - FIRST_EXTERNAL_VECTOR - 0x20;

If you are going to subtract of the number of ipis please put appropriate defines in irq_vectors.h. A raw 0x20 is wrong.

arch/x86/kernel/apic/io_apic.c int __init arch_probe_nr_irqs(void) · line 3849

Quoted 12 lines
arch/x86/kernel/apic/io_apic.c +6 -1
+
+	nr *= nr_cpu_ids;
+
+	if (nr < nr_irqs)
+		nr_irqs = nr;
 	nr = nr_irqs_gsi + 8 * nr_cpu_ids;
 #if defined(CONFIG_PCI_MSI) || defined(CONFIG_HT_IRQ)
 	/*
 	 * for MSI and HT dyn irq
 	 */
-	nr += nr_irqs_gsi * 64;
+	nr += nr_irqs_gsi * 256;

This part seems like magic voodoo. Why should their be a correlation between the number of gsis and the number of msis?

Eric

author
#38 lore raw

Re: [PATCH 2/2] x86: get more exact nr_irqs

Quoted 28 lines · Eric W. Biederman
Quoted 16 lines · Yinghai Lu

first check with NR_VECTORS - FIRST_EXTERNAL_VECTOR - 0x20 aka minus exceptions and system vectors.

NR_CPUS = 512, and nr_cpu_ids = 128
will have NR_IRQS = 256 + 512 * 64 = 33024

assume we have 20 intel ixgbe 6 port cards (with sriov and ixgbevf) 20 * 6 * 64 * 3 = 23040

first will get:
      128 * (256 - 64) = 24576
then with nr_irqs_gsi will get
      (120 + 8 * 128 + 120 * 256) = 31864

so 24576 will be used for nr_irqs.

Quoted 7 lines

24576 * 8 = 196608 bytes will be used for irq_desc_ptrs[]

before this patch:
    have nr_irqs = 120 + 8 * 128 + 120 * 64 = 8824 and irq_desc_ptrs[] is 70592

I am lost.    arch_probe_nr_irqs appears to be total nonsense.

Quoted 8 lines

We have three concepts.
- The number of irq sources we can talk about.  ( nr_irqs)
- The number of irqs we can possibly service.   ((NR_VECTORS - 0x30) *nr_cpu_ids)
- The number of irqs we actually connected up to cards in the
 system that we need to do something with.

Why do we need to allocate arrays at all?

irq_desc is allocated dynamically.

but irq_desc_ptrs is pointer array, it need to be allocated after nr_irqs is probed.

YH

#39 lore raw

Re: [PATCH 2/2] x86: get more exact nr_irqs

Quoted 35 lines · Yinghai Lu
Quoted 34 lines · Eric W. Biederman
Quoted 16 lines · Yinghai Lu

first check with NR_VECTORS - FIRST_EXTERNAL_VECTOR - 0x20 aka minus exceptions and system vectors.

NR_CPUS = 512, and nr_cpu_ids = 128
will have NR_IRQS = 256 + 512 * 64 = 33024

assume we have 20 intel ixgbe 6 port cards (with sriov and ixgbevf) 20 * 6 * 64 * 3 = 23040

first will get:
      128 * (256 - 64) = 24576
then with nr_irqs_gsi will get
      (120 + 8 * 128 + 120 * 256) = 31864

so 24576 will be used for nr_irqs.

Quoted 7 lines

24576 * 8 = 196608 bytes will be used for irq_desc_ptrs[]

before this patch:
    have nr_irqs = 120 + 8 * 128 + 120 * 64 = 8824 and irq_desc_ptrs[] is 70592

I am lost.    arch_probe_nr_irqs appears to be total nonsense.

We have three concepts.
- The number of irq sources we can talk about.  ( nr_irqs)
- The number of irqs we can possibly service.   ((NR_VECTORS - 0x30) *nr_cpu_ids)
- The number of irqs we actually connected up to cards in the
 system that we need to do something with.

Quoted 7 lines
Quoted 2 lines

Why do we need to allocate arrays at all?

irq_desc is allocated dynamically.

but irq_desc_ptrs is pointer array, it need to be allocated after nr_irqs is probed.

If we care about memory use efficiency let's replace irq_desc_ptrs with a rbtree or a radix_tree. Something that moves the memory use penalty onto those machines that have a lot of irqs.

Eric

#40 lore raw

Re: [PATCH 2/2] x86: get more exact nr_irqs

Quoted 5 lines · Eric W. Biederman

If we care about memory use efficiency let's replace irq_desc_ptrs with a rbtree or a radix_tree. Something that moves the memory use penalty onto those machines that have a lot of irqs.

rbtree doesn't make much sense for something that is addressed by index, and doesn't need to answer questions of the form "give me the highest member <= X". A hash table or radix tree makes sense, depending on the expected sparseness of the index.

-hpa

author
#41 lore raw

Re: [PATCH 2/2] x86: get more exact nr_irqs

Quoted 11 lines · H. Peter Anvin
Quoted 5 lines · Eric W. Biederman

If we care about memory use efficiency let's replace irq_desc_ptrs with a rbtree or a radix_tree. Something that moves the memory use penalty onto those machines that have a lot of irqs.

rbtree doesn't make much sense for something that is addressed by index, and doesn't need to answer questions of the form "give me the highest member <= X". A hash table or radix tree makes sense, depending on the expected sparseness of the index.

will check if we can use radix with it like powerpc

YH

#42 lore raw

Re: [PATCH 2/2] x86: get more exact nr_irqs

In reply to H. Peter Anvin
Quoted 11 lines · H. Peter Anvin
Quoted 5 lines · Eric W. Biederman

If we care about memory use efficiency let's replace irq_desc_ptrs with a rbtree or a radix_tree. Something that moves the memory use penalty onto those machines that have a lot of irqs.

rbtree doesn't make much sense for something that is addressed by index, and doesn't need to answer questions of the form "give me the highest member <= X". A hash table or radix tree makes sense, depending on the expected sparseness of the index.

Not counting irqs for msi's I think we are looking 36% to 25% fill. Maybe a little lower. The sparseness is much higher if we count the number of irqs that we might/use allocate as we do today.

Short of driver hotplug msis should be allocated densely, unless we start reserving all possible 4K msi-x vectors.

For each ioapic we allocate 16 gsis, and only maybe four of them are connected to actual pci slots.

This is essentially a slow path operation, so as long as we are not too expensive we can use any data structure we want. In kernel hash tables don't grow well so I don't think a hash table is a good choice, and a hash table is essentially what we have now.

The truth is we don't know how many irqs we will have until msi supporting drivers claim all of theirs.

I think a radix-tree would likely be the least intrusive choice as it does not imply any changes to the data structure indexed.

Eric

#43 lore raw

Re: [PATCH 2/2] x86: get more exact nr_irqs

Quoted 21 lines · Eric W. Biederman
Quoted 5 lines

rbtree doesn't make much sense for something that is addressed by index, and doesn't need to answer questions of the form "give me the highest member <= X". A hash table or radix tree makes sense, depending on the expected sparseness of the index.

Not counting irqs for msi's I think we are looking 36% to 25% fill. Maybe a little lower. The sparseness is much higher if we count the number of irqs that we might/use allocate as we do today.

Short of driver hotplug msis should be allocated densely, unless we start reserving all possible 4K msi-x vectors.

For each ioapic we allocate 16 gsis, and only maybe four of them are connected to actual pci slots.

This is essentially a slow path operation, so as long as we are not too expensive we can use any data structure we want. In kernel hash tables don't grow well so I don't think a hash table is a good choice, and a hash table is essentially what we have now.

Quoted 6 lines

The truth is we don't know how many irqs we will have until msi supporting drivers claim all of theirs.

I think a radix-tree would likely be the least intrusive choice as it does not imply any changes to the data structure indexed.

Yes, for that kind of densities radix tree is a good choice.

-hpa