Commit ff479131 authored by Martin J. Bligh's avatar Martin J. Bligh Committed by Linus Torvalds

[PATCH] make i386 topology caching

Patch originally by Matt Dobson. Reworked a little by me.

Stores the mappings between cpus and nodes in an array, instead of
working them out every time. Gives about 4% off systime for kernel
compile (we use these for every page allocation), and removes one
of the two only usages of apicid->cpu mapping, which is really awkward
to keep for systems with large apic spaces, and is genererally pretty
useless anyway (later patch removes).
parent 0b31514d
...@@ -503,6 +503,39 @@ static struct task_struct * __init fork_by_hand(void) ...@@ -503,6 +503,39 @@ static struct task_struct * __init fork_by_hand(void)
return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL); return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
} }
#ifdef CONFIG_NUMA
/* which logical CPUs are on which nodes */
volatile unsigned long node_2_cpu_mask[MAX_NR_NODES] =
{ [0 ... MAX_NR_NODES-1] = 0 };
/* which node each logical CPU is on */
volatile int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 };
/* set up a mapping between cpu and node. */
static inline void map_cpu_to_node(int cpu, int node)
{
printk("Mapping cpu %d to node %d\n", cpu, node);
node_2_cpu_mask[node] |= (1 << cpu);
cpu_2_node[cpu] = node;
}
/* undo a mapping between cpu and node. */
static inline void unmap_cpu_to_node(int cpu)
{
int node;
printk("Unmapping cpu %d from all nodes\n", cpu);
for (node = 0; node < MAX_NR_NODES; node ++)
node_2_cpu_mask[node] &= ~(1 << cpu);
cpu_2_node[cpu] = -1;
}
#else /* !CONFIG_NUMA */
#define map_cpu_to_node(cpu, node) ({})
#define unmap_cpu_to_node(cpu) ({})
#endif /* CONFIG_NUMA */
/* which physical APIC ID maps to which logical CPU number */ /* which physical APIC ID maps to which logical CPU number */
volatile int physical_apicid_2_cpu[MAX_APICID]; volatile int physical_apicid_2_cpu[MAX_APICID];
/* which logical CPU number maps to which physical APIC ID */ /* which logical CPU number maps to which physical APIC ID */
...@@ -537,6 +570,7 @@ static inline void map_cpu_to_boot_apicid(int cpu, int apicid) ...@@ -537,6 +570,7 @@ static inline void map_cpu_to_boot_apicid(int cpu, int apicid)
if (clustered_apic_mode) { if (clustered_apic_mode) {
logical_apicid_2_cpu[apicid] = cpu; logical_apicid_2_cpu[apicid] = cpu;
cpu_2_logical_apicid[cpu] = apicid; cpu_2_logical_apicid[cpu] = apicid;
map_cpu_to_node(cpu, apicid_to_node(apicid));
} else { } else {
physical_apicid_2_cpu[apicid] = cpu; physical_apicid_2_cpu[apicid] = cpu;
cpu_2_physical_apicid[cpu] = apicid; cpu_2_physical_apicid[cpu] = apicid;
...@@ -552,6 +586,7 @@ static inline void unmap_cpu_to_boot_apicid(int cpu, int apicid) ...@@ -552,6 +586,7 @@ static inline void unmap_cpu_to_boot_apicid(int cpu, int apicid)
if (clustered_apic_mode) { if (clustered_apic_mode) {
logical_apicid_2_cpu[apicid] = -1; logical_apicid_2_cpu[apicid] = -1;
cpu_2_logical_apicid[cpu] = -1; cpu_2_logical_apicid[cpu] = -1;
unmap_cpu_to_node(cpu);
} else { } else {
physical_apicid_2_cpu[apicid] = -1; physical_apicid_2_cpu[apicid] = -1;
cpu_2_physical_apicid[cpu] = -1; cpu_2_physical_apicid[cpu] = -1;
......
...@@ -27,12 +27,17 @@ ...@@ -27,12 +27,17 @@
#ifndef _ASM_I386_TOPOLOGY_H #ifndef _ASM_I386_TOPOLOGY_H
#define _ASM_I386_TOPOLOGY_H #define _ASM_I386_TOPOLOGY_H
#ifdef CONFIG_X86_NUMAQ #ifdef CONFIG_NUMA
#include <asm/smpboot.h> /* Mappings between logical cpu number and node number */
extern volatile unsigned long node_2_cpu_mask[];
extern volatile int cpu_2_node[];
/* Returns the number of the node containing CPU 'cpu' */ /* Returns the number of the node containing CPU 'cpu' */
#define __cpu_to_node(cpu) (cpu_to_logical_apicid(cpu) >> 4) static inline int __cpu_to_node(int cpu)
{
return cpu_2_node[cpu];
}
/* Returns the number of the node containing MemBlk 'memblk' */ /* Returns the number of the node containing MemBlk 'memblk' */
#define __memblk_to_node(memblk) (memblk) #define __memblk_to_node(memblk) (memblk)
...@@ -41,49 +46,22 @@ ...@@ -41,49 +46,22 @@
so it is a pretty simple function! */ so it is a pretty simple function! */
#define __parent_node(node) (node) #define __parent_node(node) (node)
/* Returns the number of the first CPU on Node 'node'. /* Returns a bitmask of CPUs on Node 'node'. */
* This should be changed to a set of cached values
* but this will do for now.
*/
static inline int __node_to_first_cpu(int node)
{
int i, cpu, logical_apicid = node << 4;
for(i = 1; i < 16; i <<= 1)
/* check to see if the cpu is in the system */
if ((cpu = logical_apicid_to_cpu(logical_apicid | i)) >= 0)
/* if yes, return it to caller */
return cpu;
BUG(); /* couldn't find a cpu on given node */
return -1;
}
/* Returns a bitmask of CPUs on Node 'node'.
* This should be changed to a set of cached bitmasks
* but this will do for now.
*/
static inline unsigned long __node_to_cpu_mask(int node) static inline unsigned long __node_to_cpu_mask(int node)
{ {
int i, cpu, logical_apicid = node << 4; return node_2_cpu_mask[node];
unsigned long mask = 0UL; }
if (sizeof(unsigned long) * 8 < NR_CPUS)
BUG();
for(i = 1; i < 16; i <<= 1)
/* check to see if the cpu is in the system */
if ((cpu = logical_apicid_to_cpu(logical_apicid | i)) >= 0)
/* if yes, add to bitmask */
mask |= 1 << cpu;
return mask; /* Returns the number of the first CPU on Node 'node'. */
static inline int __node_to_first_cpu(int node)
{
return __ffs(__node_to_cpu_mask(node));
} }
/* Returns the number of the first MemBlk on Node 'node' */ /* Returns the number of the first MemBlk on Node 'node' */
#define __node_to_memblk(node) (node) #define __node_to_memblk(node) (node)
#else /* !CONFIG_X86_NUMAQ */ #else /* !CONFIG_NUMA */
/* /*
* Other i386 platforms should define their own version of the * Other i386 platforms should define their own version of the
* above macros here. * above macros here.
...@@ -91,6 +69,6 @@ static inline unsigned long __node_to_cpu_mask(int node) ...@@ -91,6 +69,6 @@ static inline unsigned long __node_to_cpu_mask(int node)
#include <asm-generic/topology.h> #include <asm-generic/topology.h>
#endif /* CONFIG_X86_NUMAQ */ #endif /* CONFIG_NUMA */
#endif /* _ASM_I386_TOPOLOGY_H */ #endif /* _ASM_I386_TOPOLOGY_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment