topology for ia64
PATCH 1/1 topology for ia64
Hi David,
please find attached a first attempt to implement the topology.h macros/routines for IA64. We need this for the NUMA scheduler setup.
Thanks!
Best regards,
Erich
arch/ia64/kernel/acpi.c +1 -0
@@ -631,6 +631,7 @@ acpi_boot_init (char *cmdline) smp_boot_data.cpu_count = total_cpus;smp_build_cpu_map (); +build_cpu_to_node_map ();#endif /* Make boot-up look pretty */ printk ("%d CPUs available, %d CPUs total\n" , available_cpus, total_cpus);
arch/ia64/kernel/smpboot.c +27 -0
@@ -16,6 +16,7 @@#include <linux/config.h> +#include <linux/acpi.h> #include <linux/bootmem.h> #include <linux/delay.h> #include <linux/init.h>
@@ -427,6 +428,32 @@ smp_build_cpu_map (void) } } +char cpu_to_node_map[NR_CPUS] __cacheline_aligned; +/* +* Build cpu to node mapping. +*/ +void __init +build_cpu_to_node_map (void ) +{ +int cpu, i; + +for (cpu=0 ; cpu<NR_CPUS ; cpu++) { +if (!(phys_cpu_present_map & (1UL << cpu))) { + cpu_to_node_map[cpu] =-1 ; +continue ; + } +#ifdef CONFIG_ACPI_NUMA +for (i=0 ; i<NR_CPUS ; i++) +if (cpu_physical_id (cpu) == node_cpuid[i].phys_id) { + cpu_to_node_map[cpu]=node_cpuid[i].nid; +break ; + } +#else + cpu_to_node_map[cpu] =0 ; +#endif + } +} +/* * Cycle through the APs sending Wakeup IPIs to boot each. */
include/asm-ia64/smp.h +2 -0
@@ -13,6 +13,7 @@#ifdef CONFIG_SMP +#include <linux/cache.h> #include <linux/init.h> #include <linux/threads.h> #include <linux/kernel.h>
@@ -44,6 +45,7 @@ extern unsigned char smp_int_redirect;extern volatile int ia64_cpu_to_sapicid[];#define cpu_physical_id (i) ia64_cpu_to_sapicid[i] +extern char cpu_to_node_map[NR_CPUS] __cacheline_aligned;extern unsigned long ap_wakeup_vector;
include/asm-ia64/topology.h +66 -0
66 lines not on this page · raw message
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Erich Focht
Erich> Hi David, please find attached a first attempt to implement Erich> the topology.h macros/routines for IA64. We need this for the Erich> NUMA scheduler setup.
Why does the cpu_to_node_map[] exist for non-NUMA configurations? It seems to me that it would be better to make cpu_to_node_map a macro that uses an array-check for NUMA configurations and a simple test against phys_cpu_present_map() for non-NUMA.
--david
Quoted 4 lines · David Mosberger
Why does the cpu_to_node_map[] exist for non-NUMA configurations? It seems to me that it would be better to make
cpu_to_node_mapa macro that uses an array-check for NUMA configurations and a simple test againstphys_cpu_present_map()for non-NUMA.
Attached is a modified patch for implementing the topology stuff on ia64. It's on top of your 2.5.39 tree including acpi_numa and the acpi_numa fix which I've sent you separately.
I dropped the cpu_to_node_map array for the non-NUMA case. The macro __cpu_to_node() returns 0 in this case. In the places where it is used (e.g. in the NUMA scheduler) we either run on a valid CPU or have cpu_online() checks before using it, therefore I also removed the phys_cpu_present_map check when building the cpu to node map.
Hope this can be included now...
Regards,
Erich
arch/ia64/kernel/acpi.c +3 -0
@@ -784,6 +784,9 @@ acpi_boot_init (char *cmdline) smp_boot_data.cpu_count = total_cpus;smp_build_cpu_map (); +#ifdef CONFIG_NUMA +build_cpu_to_node_map (); +#endif #endif /* Make boot-up look pretty */ printk ("%d CPUs available, %d CPUs total\n" , available_cpus, total_cpus);
arch/ia64/kernel/smpboot.c +27 -0
@@ -16,6 +16,7 @@#include <linux/config.h> +#include <linux/acpi.h> #include <linux/bootmem.h> #include <linux/delay.h> #include <linux/init.h>
@@ -427,6 +428,32 @@ smp_build_cpu_map (void) } } +#ifdef CONFIG_NUMA +char cpu_to_node_map[NR_CPUS] __cacheline_aligned; +/* +* Build cpu to node mapping. +*/ +void __init +build_cpu_to_node_map (void ) +{ +int cpu, i; + +for (cpu=0 ; cpu<NR_CPUS ; cpu++) { +/* +* All Itanium NUMA platforms I know use ACPI, so maybe we +* can drop this ifdef completely. [EF] +*/ +#ifdef CONFIG_ACPI_NUMA +for (i=0 ; i<NR_CPUS ; i++) +if (cpu_physical_id (cpu) == node_cpuid[i].phys_id) { + cpu_to_node_map[cpu]=node_cpuid[i].nid; +break ; + } +#endif + } +} +#endif +/* * Cycle through the APs sending Wakeup IPIs to boot each. */
include/asm-ia64/numa.h +2 -0
@@ -22,6 +22,8 @@# define NR_MEMBLKS (NR_NODES * 8)#endif +extern char cpu_to_node_map[NR_CPUS] __cacheline_aligned; +/* Stuff below this line could be architecture independent */ extern int num_memblks;/* total number of memory chunks */
include/asm-ia64/topology.h +79 -0
79 lines not on this page · raw message
Quoted 11 lines · Erich Focht
Quoted 4 lines · David Mosberger
Why does the cpu_to_node_map[] exist for non-NUMA configurations? It seems to me that it would be better to make
cpu_to_node_mapa macro that uses an array-check for NUMA configurations and a simple test againstphys_cpu_present_map()for non-NUMA.Attached is a modified patch for implementing the topology stuff on ia64. It's on top of your 2.5.39 tree including
acpi_numaand theacpi_numafix which I've sent you separately.
Quoted 5 lines
I dropped the
cpu_to_node_maparray for the non-NUMA case. The macro__cpu_to_node()returns 0 in this case. In the places where it is used (e.g. in the NUMA scheduler) we either run on a valid CPU or havecpu_online()checks before using it, therefore I also removed thephys_cpu_present_mapcheck when building the cpu to node map.
Hi Erich! Apologies for the long response delay... I think our mail server must be a bit lagged. ;)
It looks good to me. As far as this comment:
+/*
+ * Returns the number of the first CPU on Node 'node'.
+ * Slow in the current implementation.
+ * Who needs this?
+ */
+/* #define __node_to_first_cpu(node) pool_cpus[pool_ptr[node]] */ +static inline int __node_to_first_cpu(int node)
No one is using it now. I think that I will probably deprecate this function in the near future as it is pretty useless. Anyone looking for that functionality can just do an __ffs(__node_to_cpu_mask(node)) instead, and hope that there is a reasonably quick implementation of __node_to_cpu_mask.
Quoted 1 line
Hope this can be included now...
I agree! Linus or another maintainer, please pick this up. These macros should be implemented intelligently on as many architectures as possible, now that they're beginning to be used in more and more places.
Cheers!
-Matt
Quoted 6 lines
Regards,
Erich<patch snip>
Quoted 9 lines · Matthew Dobson
Erich Focht wrote:
include/asm-ia64/topology.h +7
-0+/* +* Returns the number of the first CPU on Node 'node'. +* Slow in the current implementation. +* Who needs this? +*/ +/* #define __node_to_first_cpu(node) pool_cpus[pool_ptr[node]] */ +static inline int __node_to_first_cpu (int node)
Quoted 6 lines
No one is using it now. I think that I will probably deprecate this function in the near future as it is pretty useless. Anyone looking for that functionality can just do an __ffs(__node_to_cpu_mask(node)) instead, and hope that there is a reasonably quick implementation of
__node_to_cpu_mask.
I'm using this in the simple NUMA scheduler. This is quite useful for iterating through a specific node's CPUs. Yes, the functionality can be obtained in a different manner, but is less obvious.
Signature · 2 lines
Michael Hohnbaum 503-578-5486 [email protected] T/L 775-5486
Quoted 11 lines · Michael Hohnbaum
Quoted 9 lines · Matthew Dobson
Erich Focht wrote:
include/asm-ia64/topology.h +7
-0+/* +* Returns the number of the first CPU on Node 'node'. +* Slow in the current implementation. +* Who needs this? +*/ +/* #define __node_to_first_cpu(node) pool_cpus[pool_ptr[node]] */ +static inline int __node_to_first_cpu (int node)
Quoted 5 lines
Quoted 1 line
No one is using it now. I think that I will probably deprecate this function in the near future as it is pretty useless. Anyone looking for that functionality can just do an __ffs(__node_to_cpu_mask(node)) instead, and hope that there is a reasonably quick implementation of
__node_to_cpu_mask.I'm using this in the simple NUMA scheduler. This is quite useful for iterating through a specific node's CPUs. Yes, the functionality can be obtained in a different manner, but is less obvious.
Hmmm... This is true, but I'd like to keep the topology functions as minimal as possible. Since the functionality is so easily duplicated, and in almost every arch, is implemented almost identically, it seems a waste. In most architectures, they itterate across cpus, either returning the first one on the node, or adding each to a mask and returning that.
Besides, it's not gone yet... ;)
Cheers!
-Matt
On Tue, Oct 29, 2002 at 02:19:25PM -0800, Matthew Dobson wrote:
+/*
+ * Returns the number of the first CPU on Node 'node'.
+ * Slow in the current implementation.
+ * Who needs this?
+ */
+/* #define __node_to_first_cpu(node) pool_cpus[pool_ptr[node]] */ +static inline int __node_to_first_cpu(int node)
So far so safe... though no obvious use of it.
Quoted 5 lines · Matthew Dobson
No one is using it now. I think that I will probably deprecate this function in the near future as it is pretty useless. Anyone looking for that functionality can just do an __ffs(__node_to_cpu_mask(node)) instead, and hope that there is a reasonably quick implementation of
__node_to_cpu_mask.
This assumes the value returned by __node_to_cpu_mask() is a single word.
Bill
Quoted 10 lines · William Lee Irwin III
On Tue, Oct 29, 2002 at 02:19:25PM -0800, Matthew Dobson wrote:
include/asm-ia64/topology.h +7
-0+/* +* Returns the number of the first CPU on Node 'node'. +* Slow in the current implementation. +* Who needs this? +*/ +/* #define __node_to_first_cpu(node) pool_cpus[pool_ptr[node]] */ +static inline int __node_to_first_cpu (int node)So far so safe... though no obvious use of it.
Yep...
Quoted 6 lines · Matthew Dobson
Quoted 2 lines
No one is using it now. I think that I will probably deprecate this function in the near future as it is pretty useless. Anyone looking for that functionality can just do an __ffs(__node_to_cpu_mask(node)) instead, and hope that there is a reasonably quick implementation of
__node_to_cpu_mask.This assumes the value returned by
__node_to_cpu_mask()is a single word.
Which is the case right now. When (not if) that changes, we'll come up with more flexible ffs macros, or a better way to count variable length bitmasks... especially as there will be a TON of them.
Cheers!
-Matt
Quoted 2 lines · Matthew Dobson
Hi Erich! Apologies for the long response delay... I think our mail server must be a bit lagged. ;)
Should I use another email address?
Quoted 9 lines
It looks good to me. As far as this comment:
include/asm-ia64/topology.h +7
-0+/* +* Returns the number of the first CPU on Node 'node'. +* Slow in the current implementation. +* Who needs this? +*/ +/* #define __node_to_first_cpu(node) pool_cpus[pool_ptr[node]] */ +static inline int __node_to_first_cpu (int node)
Quoted 5 lines
No one is using it now. I think that I will probably deprecate this function in the near future as it is pretty useless. Anyone looking for that functionality can just do an __ffs(__node_to_cpu_mask(node)) instead, and hope that there is a reasonably quick implementation of
__node_to_cpu_mask.
Yes, I know of one usage meanwhile. The problem I see is: as far as I understand the CPUs are not sorted by the node numbers. The NUMA API doesn't require that, I think. So finding the first CPU in a node is not really useful for looping over the CPUs of only one node.
When you think of further developments of the NUMA API, I'd suggest two:
1: Add a sorted list of the nodes and a pointer array into that list pointing to the first CPU in the node. Like
int node_cpus[NR_CPUS];
int node_first_ptr[MAX_NUMNODES+1];
(or macros, doesn't matter).
Example: 2 nodes:
node_cpus : 0 1 4 5 2 3 6 7
node : 0 0 0 0 1 1 1 1
pointer : ^ ^ ^=> node_first_ptr[]: 0 4 8
One can initialize this easilly by using the __cpu_to_node() macro. And with this you can loop over the cpus of one node by doing:
for (i=node_first_ptr[node]; i<node_first_ptr[node+1]; i++) {
cpu = node_cpus[i];
... do stuff with cpu ...
}2: In ACPI there is a table describing the latency ratios between the nodes. It is called SLIT (System Locality Information Table). On an 8 node system (NEC TX7) this is a matrix of dimension numnodes*numnodes:
int __node_distance[ 8 * 8] = { 10, 15, 15, 15, 20, 20, 20, 20,
15, 10, 15, 15, 20, 20, 20, 20,
15, 15, 10, 15, 20, 20, 20, 20,
15, 15, 15, 10, 20, 20, 20, 20,
20, 20, 20, 20, 10, 15, 15, 15,
20, 20, 20, 20, 15, 10, 15, 15,
20, 20, 20, 20, 15, 15, 10, 15,
20, 20, 20, 20, 15, 15, 15, 10 };#define node_distance(i,j) __node_distance[i*8+j]
This means:
node_distance(i,i) = 10 (i==j: same node, lowest latency) node_distance(i,j) = 15 (i!=j: different node, same supernode) node_distance(i,j) = 20 (i!=j: different node, different
supernode)
This macro or function describes the NUMA topology of a multi-level system very well. As the table comes for free with NUMA systems with ACPI (sooner or later they'll all have this, especially if they want to run Windows, too), it would be easy to take it into the topology.h.
Regards,
Erich