[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <406ba4cc99e40548766c.1217636092@localhost>
Date: Fri, 01 Aug 2008 17:14:52 -0700
From: Jeremy Fitzhardinge <jeremy@...p.org>
To: Ingo Molnar <mingo@...e.hu>
Cc: LKML <linux-kernel@...r.kernel.org>, x86@...nel.org,
Andi Kleen <andi@...stfloor.org>,
Nick Piggin <nickpiggin@...oo.com.au>,
Jens Axboe <jens.axboe@...cle.com>
Subject: [PATCH 7 of 8] x86: make number of smp_call_function queues truely
configurable
Previously, the config option GENERIC_SMP_QUEUES was never actually
adjustable because a moderate amount of static boilerplate code had to
match.
This patch makes it truely adjustable up to the number of IPI vectors
we statically preallocate. The various IPI handlers are generated by
looping assembler macros, and their addresses are put into an array
for C code to use to actually set the vectors up.
The default number of queues is never more than NR_CPUS, and defaults
to NR_CPUS. Ideally this could be a runtime variable based on the
number of possible cpus, rather than a static compile-time options.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@...rix.com>
---
arch/x86/Kconfig | 8 +++++++-
arch/x86/kernel/apic_32.c | 18 ++++++++----------
arch/x86/kernel/entry_32.S | 12 ++++++------
arch/x86/kernel/entry_64.S | 29 ++++++++++++++++-------------
arch/x86/kernel/irqinit_64.c | 16 ++++++----------
include/asm-x86/hw_irq.h | 9 +--------
include/asm-x86/irq_vectors.h | 3 +++
include/asm-x86/mach-default/entry_arch.h | 29 ++++++++++++++++-------------
8 files changed, 63 insertions(+), 61 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -179,9 +179,15 @@
select USE_GENERIC_SMP_HELPERS
default y
+config MAX_GENERIC_SMP_QUEUES
+ int
+ default 8
+
config GENERIC_SMP_QUEUES
int
- default "8"
+ range 1 NR_CPUS if NR_CPUS <= MAX_GENERIC_SMP_QUEUES
+ range 1 MAX_GENERIC_SMP_QUEUES
+ default NR_CPUS
config X86_32_SMP
def_bool y
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -1369,6 +1369,8 @@
#ifdef CONFIG_SMP
void __init smp_intr_init(void)
{
+ int i;
+
/*
* IRQ0 must be given a fixed assignment and initialized,
* because it's used before the IO-APIC is set up.
@@ -1382,16 +1384,12 @@
alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
/* IPI for generic function call */
- BUILD_BUG_ON(CONFIG_GENERIC_SMP_QUEUES !=
- (CALL_FUNCTION_VECTOR_END - CALL_FUNCTION_VECTOR_START + 1));
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+0, call_function_interrupt0);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+1, call_function_interrupt1);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+2, call_function_interrupt2);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+3, call_function_interrupt3);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+4, call_function_interrupt4);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+5, call_function_interrupt5);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+6, call_function_interrupt6);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+7, call_function_interrupt7);
+ BUILD_BUG_ON(CONFIG_GENERIC_SMP_QUEUES > NUM_CALL_FUNCTION_VECTORS);
+ BUILD_BUG_ON(CONFIG_MAX_GENERIC_SMP_QUEUES != NUM_CALL_FUNCTION_VECTORS);
+
+ for(i = 0; i < CONFIG_GENERIC_SMP_QUEUES; i++)
+ alloc_intr_gate(CALL_FUNCTION_VECTOR_START+i,
+ callfunction_interrupts[i]);
/* IPI for single call function */
set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -688,8 +688,7 @@
ENDPROC(common_interrupt)
CFI_ENDPROC
-#define __BUILD_INTERRUPT(name, func, nr) \
-ENTRY(name) \
+#define __BUILD_INTERRUPT(func, nr) \
RING0_INT_FRAME; \
pushl $~(nr); \
CFI_ADJUST_CFA_OFFSET 4; \
@@ -698,11 +697,12 @@
movl %esp,%eax; \
call func; \
jmp ret_from_intr; \
- CFI_ENDPROC; \
+ CFI_ENDPROC;
+
+#define BUILD_INTERRUPT(name, nr) \
+ENTRY(name) \
+ __BUILD_INTERRUPT(smp_##name, nr) \
ENDPROC(name)
-
-#define BUILD_INTERRUPT(name, nr) \
- __BUILD_INTERRUPT(name, smp_##name, nr)
/* The include is where all of the SMP etc. interrupts come from */
#include "entry_arch.h"
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -870,20 +870,23 @@
END(reschedule_interrupt)
- .macro CALLFUNCTION_ENTRY num
-ENTRY(call_function_interrupt\num)
- apicinterrupt CALL_FUNCTION_VECTOR_START+\num,smp_call_function_interrupt
-END(call_function_interrupt\num)
- .endm
+.globl callfunction_interrupts
+.pushsection .rodata,"a"
+callfunction_interrupts:
+.popsection
- CALLFUNCTION_ENTRY 0
- CALLFUNCTION_ENTRY 1
- CALLFUNCTION_ENTRY 2
- CALLFUNCTION_ENTRY 3
- CALLFUNCTION_ENTRY 4
- CALLFUNCTION_ENTRY 5
- CALLFUNCTION_ENTRY 6
- CALLFUNCTION_ENTRY 7
+vec=0
+.rept CONFIG_GENERIC_SMP_QUEUES
+ ALIGN
+993: apicinterrupt CALL_FUNCTION_VECTOR_START+vec, smp_call_function_interrupt
+.pushsection .rodata,"a"
+ .quad 993b
+.popsection
+ vec = vec+1
+.endr
+.pushsection .rodata,"a"
+ .size callfunction_interrupts, . - callfunction_interrupts
+.popsection
ENTRY(call_function_single_interrupt)
apicinterrupt CALL_FUNCTION_SINGLE_VECTOR,smp_call_function_single_interrupt
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c
--- a/arch/x86/kernel/irqinit_64.c
+++ b/arch/x86/kernel/irqinit_64.c
@@ -188,16 +188,12 @@
alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
/* IPI for generic function call */
- BUILD_BUG_ON(CONFIG_GENERIC_SMP_QUEUES !=
- (CALL_FUNCTION_VECTOR_END - CALL_FUNCTION_VECTOR_START + 1));
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+0, call_function_interrupt0);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+1, call_function_interrupt1);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+2, call_function_interrupt2);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+3, call_function_interrupt3);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+4, call_function_interrupt4);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+5, call_function_interrupt5);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+6, call_function_interrupt6);
- alloc_intr_gate(CALL_FUNCTION_VECTOR_START+7, call_function_interrupt7);
+ BUILD_BUG_ON(CONFIG_GENERIC_SMP_QUEUES > NUM_CALL_FUNCTION_VECTORS);
+ BUILD_BUG_ON(CONFIG_MAX_GENERIC_SMP_QUEUES != NUM_CALL_FUNCTION_VECTORS);
+
+ for(i = 0; i < CONFIG_GENERIC_SMP_QUEUES; i++)
+ alloc_intr_gate(CALL_FUNCTION_VECTOR_START+i,
+ callfunction_interrupts[i]);
/* IPI for generic single function call */
alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
diff --git a/include/asm-x86/hw_irq.h b/include/asm-x86/hw_irq.h
--- a/include/asm-x86/hw_irq.h
+++ b/include/asm-x86/hw_irq.h
@@ -37,14 +37,7 @@
extern void irq_move_cleanup_interrupt(void);
extern void threshold_interrupt(void);
-extern void call_function_interrupt0(void);
-extern void call_function_interrupt1(void);
-extern void call_function_interrupt2(void);
-extern void call_function_interrupt3(void);
-extern void call_function_interrupt4(void);
-extern void call_function_interrupt5(void);
-extern void call_function_interrupt6(void);
-extern void call_function_interrupt7(void);
+extern void *callfunction_interrupts[CONFIG_GENERIC_SMP_QUEUES];
extern void call_function_single_interrupt(void);
diff --git a/include/asm-x86/irq_vectors.h b/include/asm-x86/irq_vectors.h
--- a/include/asm-x86/irq_vectors.h
+++ b/include/asm-x86/irq_vectors.h
@@ -79,6 +79,9 @@
#define CALL_FUNCTION_VECTOR_START 0xf0 /* f0-f7 multiple callfunction queues */
#endif
+
+#define NUM_CALL_FUNCTION_VECTORS \
+ (CALL_FUNCTION_VECTOR_END - CALL_FUNCTION_VECTOR_START + 1)
/*
* Local APIC timer IRQ vector is on a different priority level,
diff --git a/include/asm-x86/mach-default/entry_arch.h b/include/asm-x86/mach-default/entry_arch.h
--- a/include/asm-x86/mach-default/entry_arch.h
+++ b/include/asm-x86/mach-default/entry_arch.h
@@ -13,20 +13,23 @@
BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
-#define BUILD_CALLFUNCTION(n) \
- __BUILD_INTERRUPT(call_function_interrupt##n, \
- smp_call_function_interrupt, \
- CALL_FUNCTION_VECTOR_START + n)
-BUILD_CALLFUNCTION(0)
-BUILD_CALLFUNCTION(1)
-BUILD_CALLFUNCTION(2)
-BUILD_CALLFUNCTION(3)
-BUILD_CALLFUNCTION(4)
-BUILD_CALLFUNCTION(5)
-BUILD_CALLFUNCTION(6)
-BUILD_CALLFUNCTION(7)
+.pushsection .rodata,"a"
+.globl callfunction_interrupts
+callfunction_interrupts:
+.popsection
-#undef BUILD_CALLFUNCTION
+vec = 0
+.rept CONFIG_GENERIC_SMP_QUEUES
+ ALIGN
+1: __BUILD_INTERRUPT(smp_call_function_interrupt, CALL_FUNCTION_VECTOR_START+vec)
+ vec = vec+1
+.pushsection .rodata,"a"
+ .long 1b
+.popsection
+.endr
+.pushsection .rodata,"a"
+ .size callfunction_interrupts, . - callfunction_interrupts
+.popsection
#endif
/*
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists