From: Jeremy Fitzhardinge <jeremy@goop.org>
To: Ingo Molnar <mingo@elte.hu>
Cc: LKML <linux-kernel@vger.kernel.org>,
x86@kernel.org, Andi Kleen <andi@firstfloor.org>,
Nick Piggin <nickpiggin@yahoo.com.au>,
Jens Axboe <jens.axboe@oracle.com>
Subject: [PATCH 8 of 9] x86: make number of smp_call_function queues truely configurable
Date: Mon, 18 Aug 2008 11:23:45 -0700 [thread overview]
Message-ID: <3278a8beaca70a489807.1219083825@localhost> (raw)
In-Reply-To: <patchbomb.1219083817@localhost>
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@citrix.com>
---
arch/x86/Kconfig | 8 +++++++-
arch/x86/kernel/entry_32.S | 12 ++++++------
arch/x86/kernel/entry_64.S | 29 ++++++++++++++++-------------
arch/x86/kernel/irqinit_32.c | 16 ++++++----------
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, 61 insertions(+), 61 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -182,9 +182,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/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_32.c b/arch/x86/kernel/irqinit_32.c
--- a/arch/x86/kernel/irqinit_32.c
+++ b/arch/x86/kernel/irqinit_32.c
@@ -121,16 +121,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, 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
/*
next prev parent reply other threads:[~2008-08-18 21:52 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-18 18:23 [PATCH 0 of 9] x86/smp function calls: convert x86 tlb flushes to use function calls [POST 2] Jeremy Fitzhardinge
2008-08-18 18:23 ` [PATCH 1 of 9] x86: put tlb_flush_others() stats in debugfs Jeremy Fitzhardinge
2008-08-18 18:23 ` [PATCH 2 of 9] x86-32: use smp_call_function_mask for SMP TLB invalidations Jeremy Fitzhardinge
2008-08-18 18:23 ` [PATCH 3 of 9] x86-64: " Jeremy Fitzhardinge
2008-08-18 18:23 ` [PATCH 4 of 9] x86: make tlb_32|64 closer Jeremy Fitzhardinge
2008-08-18 18:23 ` [PATCH 5 of 9] x86: unify tlb.c Jeremy Fitzhardinge
2008-08-18 18:23 ` [PATCH 6 of 9] smp_function_call: add multiple queues for scalability Jeremy Fitzhardinge
2008-08-18 18:23 ` [PATCH 7 of 9] x86: add multiple smp_call_function queues Jeremy Fitzhardinge
2008-08-18 18:23 ` Jeremy Fitzhardinge [this message]
2008-08-18 18:23 ` [PATCH 9 of 9] smp function calls: add kernel parameter to disable multiple queues Jeremy Fitzhardinge
2008-08-19 0:45 ` [PATCH 0 of 9] x86/smp function calls: convert x86 tlb flushes to use function calls [POST 2] Ingo Molnar
2008-08-19 1:28 ` Ingo Molnar
2008-08-19 6:18 ` Jeremy Fitzhardinge
2008-08-19 9:27 ` Ingo Molnar
2008-08-19 14:58 ` Jeremy Fitzhardinge
2008-08-19 9:45 ` Peter Zijlstra
2008-08-19 14:58 ` Jeremy Fitzhardinge
2008-08-19 5:37 ` Jeremy Fitzhardinge
2008-08-19 9:31 ` Ingo Molnar
2008-08-19 9:56 ` Nick Piggin
2008-08-19 10:20 ` Ingo Molnar
2008-08-19 11:08 ` Nick Piggin
2008-08-19 11:44 ` Ingo Molnar
2008-08-19 10:24 ` Ingo Molnar
2008-08-19 10:49 ` Nick Piggin
2008-08-19 10:31 ` Andi Kleen
2008-08-19 11:04 ` Nick Piggin
2008-08-19 11:20 ` Andi Kleen
2008-08-19 7:32 ` Andi Kleen
2008-08-19 7:44 ` Jeremy Fitzhardinge
2008-08-19 7:48 ` Andi Kleen
2008-08-19 8:04 ` Jeremy Fitzhardinge
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3278a8beaca70a489807.1219083825@localhost \
--to=jeremy@goop.org \
--cc=andi@firstfloor.org \
--cc=jens.axboe@oracle.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=nickpiggin@yahoo.com.au \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox