Skip to contentSkip to conversation

x86_64: Support for new UV apic

RFC In review Jack Steiner 6 participants 24 messages Mar 24, 2008 – Mar 31, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC 8/8 x86_64: Support for new UV apic

UV supports really big systems. So big, in fact, that the APICID register does not contain enough bits to contain an APICID that is unique across all cpus.

The UV BIOS supports 3 APICID modes:

- legacy mode. This mode uses the old APIC mode where APICID is in bits [31:24] of the APICID register.

- x2apic mode. This mode is whitebox-compatible. APICIDs are unique across all cpus. Standard x2apic APIC operations (Intel-defined) can be used for IPIs. The node identifier fits within the Intel-defined portion of the APICID register.

- x2apic-uv mode. In this mode, the APICIDs on each node have unique IDs, but IDs on different node are not unique. For example, if each mode has 32 cpus, the APICIDs on each node might be 0 - 31. Every node has the same set of IDs.
The UV hub is used to route IPIs/interrupts to the correct node. Traditional APIC operations WILL NOT WORK.

In x2apic-uv mode, the ACPI tables all contain a full unique ID (note:
exact bit layout still changing but the following is close):

nnnnnnnnnnlc0cch
n = unique node number
l = socket number on board
c = core
h = hyperthread

Only the "lc0cch" bits are written to the APICID register. The remaining bits are supplied by having the get_apic_id() function "OR" the extra bits into the value read from the APICID register. (Hmmm.. why not keep the ENTIRE APICID register in per-cpu data....)

The x2apic-uv mode is recognized by the MADT table containing:

	  oem_id = "SGI"
	  oem_table_id = "UV-X"

(NOTE: a work-in-progress. Pieces missing....)

---
 arch/x86/kernel/Makefile         |    2 
 arch/x86/kernel/genapic_64.c     |   15 +
 arch/x86/kernel/genx2apic_uv_x.c |  305 +++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/setup64.c        |    4 
 arch/x86/kernel/smpboot_64.c     |    7 
 include/asm-x86/genapic_64.h     |    5 
 6 files changed, 335 insertions(+), 3 deletions(-)
arch/x86/kernel/genapic_64.c +14 -1
Index: linux/arch/x86/kernel/genapic_64.c
===================================================================
@@ -30,6 +30,7 @@ u16 x86_cpu_to_apicid_init[NR_CPUS] __in
 void *x86_cpu_to_apicid_early_ptr;
 DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID;
 EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
+DEFINE_PER_CPU(int, x2apic_extra_bits);
 
 struct genapic __read_mostly *genapic = &apic_flat;
 
@@ -40,6 +41,9 @@ static enum uv_system_type uv_system_typ
  */
 void __init setup_apic_routing(void)
 {
+	if (uv_system_type == UV_NON_UNIQUE_APIC)
+		genapic = &apic_x2apic_uv_x;
+	else
 #ifdef CONFIG_ACPI
 	/*
 	 * Quirk: some x86_64 machines can only use physical APIC mode
@@ -69,7 +73,16 @@ void send_IPI_self(int vector)
 
 unsigned int get_apic_id(void)
 {
-	return (apic_read(APIC_ID) >> 24) & 0xFFu;
+	unsigned int id;
+
+	preempt_disable();
+	id = apic_read(APIC_ID);
+	if (uv_system_type >= UV_X2APIC)
+		id  |= __get_cpu_var(x2apic_extra_bits);
+	else
+		id = (id >> 24) & 0xFFu;;
+	preempt_enable();
+	return id;
 }
 
 int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
arch/x86/kernel/genx2apic_uv_x.c new file +305 -0

305 lines not on this page · raw message

arch/x86/kernel/setup64.c +4 -0
Index: linux/arch/x86/kernel/setup64.c
===================================================================
@@ -24,6 +24,7 @@
 #include <asm/proto.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
+#include <asm/genapic.h>
 
 #ifndef CONFIG_DEBUG_BOOT_PARAMS
 struct boot_params __initdata boot_params;
@@ -355,4 +356,7 @@ void __cpuinit cpu_init (void)
 	fpu_init(); 
 
 	raw_local_save_flags(kernel_eflags);
+
+	if (is_uv_system())
+		uv_cpu_init();
 }
arch/x86/kernel/Makefile +1 -1
Index: linux/arch/x86/kernel/Makefile
===================================================================
@@ -90,7 +90,7 @@ scx200-y			+= scx200_32.o
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
-        obj-y				+= genapic_64.o genapic_flat_64.o
+        obj-y				+= genapic_64.o genapic_flat_64.o genx2apic_uv_x.o
         obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer_64.o
         obj-$(CONFIG_AUDIT)		+= audit_64.o
 
arch/x86/kernel/smpboot_64.c +6 -1
Index: linux/arch/x86/kernel/smpboot_64.c
===================================================================
@@ -60,6 +60,7 @@
 #include <asm/hw_irq.h>
 #include <asm/numa.h>
 #include <asm/trampoline.h>
+#include <asm/genapic.h>
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
@@ -418,6 +419,9 @@ static int __cpuinit wakeup_secondary_vi
 	unsigned long send_status, accept_status = 0;
 	int maxlvt, num_starts, j;
 
+	if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
+		return uv_wakeup_secondary(phys_apicid, start_rip);
+
 	Dprintk("Asserting INIT.\n");
 
 	/*
@@ -679,7 +683,8 @@ do_rest:
 				/* trampoline code not run */
 				printk("Not responding.\n");
 #ifdef APIC_DEBUG
-			inquire_remote_apic(apicid);
+			if (get_uv_system_type() != UV_NON_UNIQUE_APIC)
+				inquire_remote_apic(apicid);
 #endif
 		}
 	}
include/asm-x86/genapic_64.h +5 -0
Index: linux/include/asm-x86/genapic_64.h
===================================================================
@@ -39,4 +39,9 @@ enum uv_system_type {UV_NONE, UV_LEGACY_
 extern enum uv_system_type get_uv_system_type(void);
 extern int is_uv_system(void);
 
+extern struct genapic apic_x2apic_uv_x;
+DECLARE_PER_CPU(int, x2apic_extra_bits);
+extern void uv_cpu_init(void);
+extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip);
+
 #endif

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#1 lore raw

arch/x86/kernel/genapic_64.c void send_IPI_self(int vector) · line 85

Quoted 13 lines · Jack Steiner

unsigned int get_apic_id(void)
{

arch/x86/kernel/genapic_64.c +10 -1
-	return (apic_read(APIC_ID) >> 24) & 0xFFu;
+	unsigned int id;
+
+	preempt_disable();
+	id = apic_read(APIC_ID);
+	if (uv_system_type >= UV_X2APIC)
+		id  |= __get_cpu_var(x2apic_extra_bits);
+	else
+		id = (id >> 24) & 0xFFu;;
+	preempt_enable();
+	return id;

Really caller should have done preempt_disable(), otherwise the value can be wrong as soon as you return.

Better probably to just WARN_ON if preemption is on

(just be careful it does not trigger in oopses and machine checks)

arch/x86/kernel/genx2apic_uv_x.c line 27

Quoted 3 lines
arch/x86/kernel/genx2apic_uv_x.c new file +3 -0
+
+DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
+EXPORT_PER_CPU_SYMBOL(__uv_hub_info);

GPL export too?

Quoted 5 lines
arch/x86/kernel/genx2apic_uv_x.c new file +5 -0
+
+struct uv_blade_info *uv_blade_info;
+EXPORT_SYMBOL_GPL(uv_blade_info);
+
+short *uv_node_to_blade;

arch/x86/kernel/genx2apic_uv_x.c line 42

Quoted 10 lines
arch/x86/kernel/genx2apic_uv_x.c new file +10 -0
+EXPORT_SYMBOL_GPL(uv_node_to_blade);
+
+short *uv_cpu_to_blade;
+EXPORT_SYMBOL_GPL(uv_cpu_to_blade);
+
+short uv_possible_blades;
+EXPORT_SYMBOL_GPL(uv_possible_blades);
+
+/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
+/* Probably incorrect for UV  ZZZ */

Actually it should be correct. Except for UV you likely really need a NUMA aware irqbalanced. I used to have some old very hackish patches to implement that in irqbalanced, but never pushed it because the systems I was working on didn't really need it.

arch/x86/kernel/genx2apic_uv_x.c line 78

Quoted 7 lines
arch/x86/kernel/genx2apic_uv_x.c new file +7 -0
+
+static void uv_send_IPI_one(int cpu, int vector)
+{
+	unsigned long val, apicid;
+	int nasid;
+
+	apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */

Instead of doing that it might be better to implement __read_mostly per CPU variables (should not be very hard)

arch/x86/kernel/genx2apic_uv_x.c line 99

Quoted 10 lines
arch/x86/kernel/genx2apic_uv_x.c new file +10 -0
+static void uv_send_IPI_mask(cpumask_t mask, int vector)
+{
+	unsigned long flags;
+	unsigned int cpu;
+
+	local_irq_save(flags);
+	for (cpu = 0; cpu < NR_CPUS; ++cpu)
+		if (cpu_isset(cpu, mask))
+			uv_send_IPI_one(cpu, vector);
+	local_irq_restore(flags);

This could disable interrupts for a long time could't it? Really needed?

arch/x86/kernel/genx2apic_uv_x.c line 196

Quoted 3 lines
arch/x86/kernel/genx2apic_uv_x.c new file +3 -0
+	bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
+	uv_blade_info = alloc_bootmem_pages(bytes);
+	memset(uv_blade_info, 255, bytes);

255? Strange poison value.

arch/x86/kernel/Makefile scx200-y += scx200_32.o · line 93

Quoted 9 lines

===================================================================

arch/x86/kernel/Makefile +1 -1
@@ -90,7 +90,7 @@ scx200-y			+= scx200_32.o
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
-        obj-y				+= genapic_64.o genapic_flat_64.o
+        obj-y				+= genapic_64.o genapic_flat_64.o genx2apic_uv_x.o

Definitely should be a CONFIG

arch/x86/kernel/Makefile static int __cpuinit wakeup_secondary_vi · line 424

Quoted 7 lines
arch/x86/kernel/Makefile +3 -0
@@ -418,6 +419,9 @@ static int __cpuinit wakeup_secondary_vi
 	unsigned long send_status, accept_status = 0;
 	int maxlvt, num_starts, j;
 
+	if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
+		return uv_wakeup_secondary(phys_apicid, start_rip);
+

This should be probably factored properly (didn't Jeremy have smp_ops for this some time ago) so that even the default case is a call.

arch/x86/kernel/Makefile do_rest: · line 687

Quoted 10 lines
arch/x86/kernel/Makefile +2 -1
 	Dprintk("Asserting INIT.\n");
 
 	/*
@@ -679,7 +683,8 @@ do_rest:
 				/* trampoline code not run */
 				printk("Not responding.\n");
 #ifdef APIC_DEBUG
-			inquire_remote_apic(apicid);
+			if (get_uv_system_type() != UV_NON_UNIQUE_APIC)
+				inquire_remote_apic(apicid);

Dito.

-Andi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#2 lore raw
Quoted 19 lines · Andi Kleen

arch/x86/kernel/genapic_64.c void send_IPI_self(int vector) · line 85

Quoted 13 lines · Jack Steiner

unsigned int get_apic_id(void)
{

arch/x86/kernel/genapic_64.c +10 -1
-	return (apic_read(APIC_ID) >> 24) & 0xFFu;
+	unsigned int id;
+
+	preempt_disable();
+	id = apic_read(APIC_ID);
+	if (uv_system_type >= UV_X2APIC)
+		id  |= __get_cpu_var(x2apic_extra_bits);
+	else
+		id = (id >> 24) & 0xFFu;;
+	preempt_enable();
+	return id;

Really caller should have done preempt_disable(), otherwise the value can be wrong as soon as you return.

Quoted 1 line

Better probably to just WARN_ON if preemption is on

Will do (assuming it doesn't ripple thru too much code eliminating warnings - doesn't look bad at first glance).

Quoted 8 lines

(just be careful it does not trigger in oopses and machine checks)

arch/x86/kernel/genx2apic_uv_x.c line 27

Quoted 3 lines
arch/x86/kernel/genx2apic_uv_x.c new file +3 -0
+
+DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
+EXPORT_PER_CPU_SYMBOL(__uv_hub_info);

GPL export too?

Yes.

Quoted 13 lines
Quoted 13 lines
arch/x86/kernel/genx2apic_uv_x.c new file +12 -0
+
+struct uv_blade_info *uv_blade_info;
+EXPORT_SYMBOL_GPL(uv_blade_info);
+
+short *uv_node_to_blade;
+EXPORT_SYMBOL_GPL(uv_node_to_blade);
+
+short *uv_cpu_to_blade;
+EXPORT_SYMBOL_GPL(uv_cpu_to_blade);
+
+short uv_possible_blades;
+EXPORT_SYMBOL_GPL(uv_possible_blades);
Quoted 8 lines

arch/x86/kernel/genx2apic_uv_x.c line 42

Quoted 3 lines
arch/x86/kernel/genx2apic_uv_x.c new file +3 -0
+
+/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
+/* Probably incorrect for UV  ZZZ */

Actually it should be correct. Except for UV you likely really need a NUMA aware irqbalanced. I used to have some old very hackish patches to implement that in irqbalanced, but never pushed it because the systems I was working on didn't really need it.

Deleted comment.

Quoted 12 lines

arch/x86/kernel/genx2apic_uv_x.c line 78

Quoted 9 lines
arch/x86/kernel/genx2apic_uv_x.c new file +7 -0
+
+static void uv_send_IPI_one(int cpu, int vector)
+{
+	unsigned long val, apicid;
+	int nasid;
+
+	apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */

Instead of doing that it might be better to implement __read_mostly per CPU variables (should not be very hard)

Added to list of loose-ends that need addressing.

Quoted 13 lines

arch/x86/kernel/genx2apic_uv_x.c line 99

Quoted 11 lines
arch/x86/kernel/genx2apic_uv_x.c new file +10 -0
+static void uv_send_IPI_mask(cpumask_t mask, int vector)
+{
+	unsigned long flags;
+	unsigned int cpu;
+
+	local_irq_save(flags);
+	for (cpu = 0; cpu < NR_CPUS; ++cpu)
+		if (cpu_isset(cpu, mask))
+			uv_send_IPI_one(cpu, vector);
+	local_irq_restore(flags);

This could disable interrupts for a long time could't it? Really needed?

No, not sure why I did that. Deleted the irq disable...

Quoted 7 lines

arch/x86/kernel/genx2apic_uv_x.c line 196

Quoted 5 lines
arch/x86/kernel/genx2apic_uv_x.c new file +3 -0
+	bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
+	uv_blade_info = alloc_bootmem_pages(bytes);
+	memset(uv_blade_info, 255, bytes);

255? Strange poison value.

Deleted the memset. Should not be depending on poison values. Was useful in debugging but it has outlived it's usefulness.

Quoted 12 lines

arch/x86/kernel/Makefile scx200-y += scx200_32.o · line 93

Quoted 10 lines

===================================================================

arch/x86/kernel/Makefile +1 -1
@@ -90,7 +90,7 @@ scx200-y			+= scx200_32.o
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
-        obj-y				+= genapic_64.o genapic_flat_64.o
+        obj-y				+= genapic_64.o genapic_flat_64.o genx2apic_uv_x.o

Definitely should be a CONFIG

Not sure that I understand why. The overhead of UV is minimal & we want UV enabled in all distro kernels. OTOH, small embedded systems probably want to eliminate every last bit of unneeded code.

Might make sense to have a config option. Thoughts????

Quoted 11 lines

arch/x86/kernel/Makefile static int __cpuinit wakeup_secondary_vi · line 424

Quoted 8 lines
arch/x86/kernel/Makefile +3 -0
@@ -418,6 +419,9 @@ static int __cpuinit wakeup_secondary_vi
 	unsigned long send_status, accept_status = 0;
 	int maxlvt, num_starts, j;
 
+	if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
+		return uv_wakeup_secondary(phys_apicid, start_rip);
+

This should be probably factored properly (didn't Jeremy have smp_ops for this some time ago) so that even the default case is a call.

By factored, do you means something like:

	is_uv_legacy_system()
	is_us_non_unique_apicid_system()
	...

Or maybe:
is_uv_system_type(x) # where x is UV_NON_UNIQUE_APIC, etc

Quoted 1 line

-Andi

Thanks for the careful review.

--- jack

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw
Quoted 10 lines
Quoted 2 lines

This should be probably factored properly (didn't Jeremy have smp_ops for this some time ago) so that even the default case is a call.

By factored, do you means something like:

	is_uv_legacy_system()
	is_us_non_unique_apicid_system()
	...

Or maybe:
is_uv_system_type(x) # where x is UV_NON_UNIQUE_APIC, etc

No instead of having lots of if (xyz_system) do_xyz_special() go through smp_ops for the whole thing so that UV would just have a special smp_ops that has special implementions or wrappers.

Oops I see smp_ops are currently only implemented for 32bit. Ok do it only once smp_ops exist on 64bit too.

-Andi

#4 lore raw
Quoted 6 lines · Andi Kleen

No instead of having lots of if (xyz_system) do_xyz_special()
go through smp_ops for the whole thing so that UV would just have a special smp_ops that has special implementions or wrappers.

Oops I see smp_ops are currently only implemented for 32bit. Ok do it only once smp_ops exist on 64bit too.

I think glommer has patches to unify smp stuff, which should include smp_ops.

J

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw
Quoted 5 lines · Jeremy Fitzhardinge
Quoted 4 lines · Andi Kleen

No instead of having lots of if (xyz_system) do_xyz_special() go through smp_ops for the whole thing so that UV would just have a special smp_ops that has special implementions or wrappers.

Quoted 7 lines
Quoted 3 lines

Oops I see smp_ops are currently only implemented for 32bit. Ok do it only once smp_ops exist on 64bit too.

I think glommer has patches to unify smp stuff, which should include smp_ops.

They are already merged in ingo's tree.

I'm still about to post some last-minute issues, but the full smp_ops support is there.

Signature · 11 lines
Glauber Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#6 lore raw
In reply to Jeremy Fitzhardinge
Quoted 9 lines · Jeremy Fitzhardinge
Quoted 5 lines · Andi Kleen

No instead of having lots of if (xyz_system) do_xyz_special() go through smp_ops for the whole thing so that UV would just have a special smp_ops that has special implementions or wrappers. Oops I see smp_ops are currently only implemented
for 32bit. Ok do it only once smp_ops exist on 64bit too.

I think glommer has patches to unify smp stuff, which should include smp_ops.

yep, x86.git/latest has all that work included.

Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw
In reply to Jack Steiner
Quoted 10 lines · Jack Steiner
Quoted 4 lines

arch/x86/kernel/Makefile scx200-y += scx200_32.o · line 93

Quoted 2 lines
arch/x86/kernel/Makefile +1 -1
-        obj-y				+= genapic_64.o genapic_flat_64.o
+        obj-y				+= genapic_64.o genapic_flat_64.o genx2apic_uv_x.o

Definitely should be a CONFIG

Not sure that I understand why. The overhead of UV is minimal & we want UV enabled in all distro kernels. OTOH, small embedded systems probably want to eliminate every last bit of unneeded code.

Might make sense to have a config option. Thoughts????

i wouldnt mind having UV enabled by default (it can be a config option but default-enabled on generic kernels so all distros will pick this hw support up), but we definitely need the genapic unification before we can add more features.

Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw
Quoted 12 lines · Ingo Molnar
Quoted 9 lines · Jack Steiner
Quoted 4 lines

arch/x86/kernel/Makefile scx200-y += scx200_32.o · line 93

Quoted 2 lines
arch/x86/kernel/Makefile +1 -1
-        obj-y                            += genapic_64.o genapic_flat_64.o
+        obj-y                            += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o

Definitely should be a CONFIG

Not sure that I understand why. The overhead of UV is minimal & we want UV enabled in all distro kernels. OTOH, small embedded systems probably want to eliminate every last bit of unneeded code.

Quoted 6 lines
Quoted 1 line

Might make sense to have a config option. Thoughts????

i wouldnt mind having UV enabled by default (it can be a config option but default-enabled on generic kernels so all distros will pick this hw support up), but we definitely need the genapic unification before we can add more features.

config option would be reasonable.
for x86_64
subarch already have X86_PC, X86_VSMP.
we have X86_UVSMP

YH

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw
Quoted 20 lines · Yinghai Lu
Quoted 12 lines · Ingo Molnar
Quoted 9 lines · Jack Steiner
Quoted 4 lines

arch/x86/kernel/Makefile scx200-y += scx200_32.o · line 93

Quoted 2 lines
arch/x86/kernel/Makefile +1 -1
-        obj-y                            += genapic_64.o genapic_flat_64.o
+        obj-y                            += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o

Definitely should be a CONFIG

Not sure that I understand why. The overhead of UV is minimal & we want UV enabled in all distro kernels. OTOH, small embedded systems probably want to eliminate every last bit of unneeded code.

Quoted 6 lines
Quoted 1 line

Might make sense to have a config option. Thoughts????

i wouldnt mind having UV enabled by default (it can be a config option but default-enabled on generic kernels so all distros will pick this hw support up), but we definitely need the genapic unification before we can add more features.

Quoted 4 lines

config option would be reasonable.
for x86_64
subarch already have X86_PC, X86_VSMP.
we have X86_UVSMP

If there was a significant differece between UV and generic kernels (or hardware), then I would agree. However, the only significant difference is the APIC model on large systems. Small systems are exactly compatible.

The problem with subarch is that we want 1 binary kernel to support both generic hardware AND uv hardware. This restriction is desirable for the distros and software vendors. Otherwise, additional kernel images would have to be built, released, & certified.

--- jack

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#10 lore raw
Quoted 6 lines

If there was a significant differece between UV and generic kernels (or hardware), then I would agree. However, the only significant difference is the APIC model on large systems. Small systems are exactly compatible.

The problem with subarch is that we want 1 binary kernel to support

x86-64 subarchs are more options than true subarchs. They generally do not prevent the kernel from running on other systems, just control addition of some additional code or special data layout. They are quite different from the i386 subarchs or those of other architectures.

The main reason vSMP is called a subarch is that it pads a lot of data structures to 4K and you don't really want that on your normal kernel, but there isn't anything in there that would prevent booting on a normal system.

The UV option certainly doesn't have this issue.

Quoted 3 lines

both generic hardware AND uv hardware. This restriction is desirable for the distros and software vendors. Otherwise, additional kernel images would have to be built, released, & certified.

I think an option would be fine, just don't call it a subarch. I don't feel strongly about it, as you point out it is not really very much code.

-Andi

#11 lore raw
Quoted 20 lines · Andi Kleen
Quoted 6 lines

If there was a significant differece between UV and generic kernels (or hardware), then I would agree. However, the only significant difference is the APIC model on large systems. Small systems are exactly compatible.

The problem with subarch is that we want 1 binary kernel to support

x86-64 subarchs are more options than true subarchs. They generally do not prevent the kernel from running on other systems, just control addition of some additional code or special data layout. They are quite different from the i386 subarchs or those of other architectures.

The main reason vSMP is called a subarch is that it pads a lot of data structures to 4K and you don't really want that on your normal kernel, but there isn't anything in there that would prevent booting on a normal system.

The UV option certainly doesn't have this issue.

Quoted 7 lines
Quoted 3 lines

both generic hardware AND uv hardware. This restriction is desirable for the distros and software vendors. Otherwise, additional kernel images would have to be built, released, & certified.

I think an option would be fine, just don't call it a subarch. I don't feel strongly about it, as you point out it is not really very much code.

if the calling path like GET_APIC_ID is keeping checking if it is UV box after boot time, that may not good.

don't need make other hundreds of machine keep running the code only for several big box all the time.

YH

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#12 lore raw
Quoted 8 lines

if the calling path like GET_APIC_ID is keeping checking if it is UV box after boot time, that may not good.

don't need make other hundreds of machine keep running the code only for several big box all the time.

YH

I added trace code to see how often GET_APIC_ID() is called. For my 8p AMD box, the function is called 6 times per cpu during boot. I have not seen any other calls to the function after early boot although I'm they occur under some circumstances.

Can you think of a workload where the frequency of calls is high enough to be significant??

--- jack

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#13 lore raw
Quoted 7 lines · Jack Steiner
Quoted 7 lines

if the calling path like GET_APIC_ID is keeping checking if it is UV box after boot time, that may not good.

don't need make other hundreds of machine keep running the code only for several big box all the time.

Quoted 7 lines
Quoted 1 line

YH

I added trace code to see how often GET_APIC_ID() is called. For my 8p AMD box, the function is called 6 times per cpu during boot. I have not seen any other calls to the function after early boot although I'm they occur under some circumstances.

then it is ok.

YH

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#14 lore raw
Quoted 11 lines · Yinghai Lu
Quoted 10 lines · Jack Steiner
Quoted 8 lines

if the calling path like GET_APIC_ID is keeping checking if it is UV box after boot time, that may not good.

don't need make other hundreds of machine keep running the code only for several big box all the time.

YH

Quoted 6 lines
Quoted 4 lines

I added trace code to see how often GET_APIC_ID() is called. For my 8p AMD box, the function is called 6 times per cpu during boot. I have not seen any other calls to the function after early boot although I'm they occur under some circumstances.

then it is ok.

yes - and even if it were called more frequently, having generic code and having the possibility of an as generic as possible kernel image (and kernel rpms) is still a very important feature. In that sense subarch support is actively harmful and we are trying to move away from that model.

It is very nice that Jack has managed to make UV a generic platform instead of a subarch - and i'd encourage all future PC platform extensions to work via that model. The status of current PC subarchitectures is the following:

- mach-visws: obsolete. We could drop it today - it's been years since i saw real VISWS bugreports.

- mach-voyager: obsolete.

- mach-es7000: on the way out - latest ES7000's are generic.

- mach-rdc321x: it's being de-sub-architectured. It's about one patch away from becoming a non-subarch.

so we are just a few patches and a few well-directed voltage spikes away from being able to remove the subarch complication from x86 altogether ;-)

Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#15 lore raw
Quoted 1 line

- mach-voyager: obsolete.

You just have to convince James @)

Quoted 2 lines

- mach-es7000: on the way out - latest ES7000's are generic.

That would mean dropping support for prev-gen es7000 which are not that old actually (only a few years). But I think with a little effort the old es7000 code could be fit into the generic architecture. It is not that far away from a normal PC.

Quoted 3 lines

- mach-rdc321x: it's being de-sub-architectured. It's about one patch away from becoming a non-subarch.

mach-numaq (not in arch, but spread out all over the port)
I hear there are only a one or two machines running left. Unfortunately they are in test.kernel.org, but hopefully they will die soon.
NUMAQ has quite a lot of ugly ifdefs and special cases that would be great to eliminate

mach-bigsmp/mach-summit (also in asm only)
obsolete, should be deprecated for mach-generic (just generic currently pulls in code from them)
A good first step would be to just disable the separate CONFIG options and only allow using them through generic.

-Andi

#16 lore raw
In reply to Ingo Molnar
Quoted 20 lines · Ingo Molnar
Quoted 16 lines · Yinghai Lu
Quoted 14 lines · Jack Steiner
Quoted 8 lines

if the calling path like GET_APIC_ID is keeping checking if it is UV box after boot time, that may not good.

don't need make other hundreds of machine keep running the code only for several big box all the time.

YH

I added trace code to see how often GET_APIC_ID() is called. For my 8p AMD box, the function is called 6 times per cpu during boot. I have not seen any other calls to the function after early boot although I'm they occur under some circumstances.

Quoted 7 lines
Quoted 1 line

then it is ok.

yes - and even if it were called more frequently, having generic code and having the possibility of an as generic as possible kernel image (and kernel rpms) is still a very important feature. In that sense subarch support is actively harmful and we are trying to move away from that model.

regarding LinuxBIOS = coreboot + TinyKernel. some box need to use 64bit kernel, because 32 bit kernel could mess up the 64 bit resources, and final kernel kexeced is 64 bit.

and TinyKernel need to stay with coreboot in MB flash rom, and that flash is about 2M...

So hope it is easier to use MACRO to mask platform detect code out.

YH

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#17 lore raw
In reply to Yinghai Lu
Quoted 2 lines

if the calling path like GET_APIC_ID is keeping checking if it is UV box after boot time, that may not good.

I don't think GET_APIC_ID is anywhere on a critical path. As long as it doesn't lead to code bloat that shouldn't be an issue.

-Andi

#18 lore raw
In reply to Jack Steiner
Quoted 7 lines · Jack Steiner

Index: linux/arch/x86/kernel/genapic_64.c

arch/x86/kernel/genapic_64.c +0 -1
@@ -69,7 +73,16 @@ void send_IPI_self(int vector)
 
 unsigned int get_apic_id(void)
 {
-	return (apic_read(APIC_ID) >> 24) & 0xFFu;

arch/x86/kernel/genapic_64.c void send_IPI_self(int vector) · line 85

Quoted 10 lines
arch/x86/kernel/genapic_64.c +10 -0
+	unsigned int id;
+
+	preempt_disable();
+	id = apic_read(APIC_ID);
+	if (uv_system_type >= UV_X2APIC)
+		id  |= __get_cpu_var(x2apic_extra_bits);
+	else
+		id = (id >> 24) & 0xFFu;;
+	preempt_enable();
+	return id;

dont we want to put get_apic_id() into struct genapic instead? We already have ID management there.

also, we want to unify 32-bit and 64-bit genapic code and just have genapic all across x86.

Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#19 lore raw
Quoted 24 lines · Ingo Molnar
Quoted 7 lines · Jack Steiner

Index: linux/arch/x86/kernel/genapic_64.c

arch/x86/kernel/genapic_64.c +0 -1
@@ -69,7 +73,16 @@ void send_IPI_self(int vector)
 
 unsigned int get_apic_id(void)
 {
-	return (apic_read(APIC_ID) >> 24) & 0xFFu;

arch/x86/kernel/genapic_64.c void send_IPI_self(int vector) · line 85

Quoted 10 lines
arch/x86/kernel/genapic_64.c +10 -0
+	unsigned int id;
+
+	preempt_disable();
+	id = apic_read(APIC_ID);
+	if (uv_system_type >= UV_X2APIC)
+		id  |= __get_cpu_var(x2apic_extra_bits);
+	else
+		id = (id >> 24) & 0xFFu;;
+	preempt_enable();
+	return id;

dont we want to put get_apic_id() into struct genapic instead? We already have ID management there.

Quoted 2 lines

also, we want to unify 32-bit and 64-bit genapic code and just have genapic all across x86.

Long term, I think that makes sense. However, I think that should be a separate series of patches since there are significant differences between the 32-bit and 64-bit genapic structs.

--- jack

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#20 lore raw
Quoted 25 lines · Jack Steiner
Quoted 24 lines · Ingo Molnar
Quoted 7 lines · Jack Steiner

Index: linux/arch/x86/kernel/genapic_64.c

arch/x86/kernel/genapic_64.c +0 -1
@@ -69,7 +73,16 @@ void send_IPI_self(int vector)
 
 unsigned int get_apic_id(void)
 {
-   return (apic_read(APIC_ID) >> 24) & 0xFFu;

arch/x86/kernel/genapic_64.c void send_IPI_self(int vector) · line 85

Quoted 10 lines
arch/x86/kernel/genapic_64.c +10 -0
+   unsigned int id;
+
+   preempt_disable();
+   id = apic_read(APIC_ID);
+   if (uv_system_type >= UV_X2APIC)
+           id  |= __get_cpu_var(x2apic_extra_bits);
+   else
+           id = (id >> 24) & 0xFFu;;
+   preempt_enable();
+   return id;

dont we want to put get_apic_id() into struct genapic instead? We already have ID management there.

Quoted 7 lines
Quoted 2 lines

also, we want to unify 32-bit and 64-bit genapic code and just have genapic all across x86.

Long term, I think that makes sense. However, I think that should be a separate series of patches since there are significant differences between the 32-bit and 64-bit genapic structs.

However, if you add more code, they'll keep diverging. The moment you touch them, and get your
hands warmed up, is the perfect moment for an integration series.

Signature · 11 lines
Glauber Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#21 lore raw
In reply to Jack Steiner
Quoted 84 lines · Jack Steiner

UV supports really big systems. So big, in fact, that the APICID register does not contain enough bits to contain an APICID that is unique across all cpus.

The UV BIOS supports 3 APICID modes:

- legacy mode. This mode uses the old APIC mode where APICID is in bits [31:24] of the APICID register.

- x2apic mode. This mode is whitebox-compatible. APICIDs are unique across all cpus. Standard x2apic APIC operations (Intel-defined) can be used for IPIs. The node identifier fits within the Intel-defined portion of the APICID register.

- x2apic-uv mode. In this mode, the APICIDs on each node have unique IDs, but IDs on different node are not unique. For example, if each mode has 32 cpus, the APICIDs on each node might be 0 - 31. Every node has the same set of IDs.
The UV hub is used to route IPIs/interrupts to the correct node. Traditional APIC operations WILL NOT WORK.

In x2apic-uv mode, the ACPI tables all contain a full unique ID (note:
exact bit layout still changing but the following is close):

nnnnnnnnnnlc0cch
n = unique node number
l = socket number on board
c = core
h = hyperthread

Only the "lc0cch" bits are written to the APICID register. The remaining bits are supplied by having the get_apic_id() function "OR" the extra bits into the value read from the APICID register. (Hmmm.. why not keep the ENTIRE APICID register in per-cpu data....)

The x2apic-uv mode is recognized by the MADT table containing:

          oem_id = "SGI"
          oem_table_id = "UV-X"

(NOTE: a work-in-progress. Pieces missing....)

---

  arch/x86/kernel/Makefile         |    2
  arch/x86/kernel/genapic_64.c     |   15 +
  arch/x86/kernel/genx2apic_uv_x.c |  305 +++++++++++++++++++++++++++++++++++++++
  arch/x86/kernel/setup64.c        |    4
  arch/x86/kernel/smpboot_64.c     |    7
  include/asm-x86/genapic_64.h     |    5
  6 files changed, 335 insertions(+), 3 deletions(-)

Index: linux/arch/x86/kernel/genapic_64.c
===================================================================
--- linux.orig/arch/x86/kernel/genapic_64.c 2008-03-21 15:37:05.000000000 -0500
+++ linux/arch/x86/kernel/genapic_64.c 2008-03-21 15:49:38.000000000 -0500 @@ -30,6 +30,7 @@ u16 x86_cpu_to_apicid_init[NR_CPUS] __in
void *x86_cpu_to_apicid_early_ptr;
DEFINE_PER_CPU(u16, x86_cpu_to_apicid) = BAD_APICID; EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid);
+DEFINE_PER_CPU(int, x2apic_extra_bits);

  struct genapic __read_mostly *genapic = &apic_flat;

@@ -40,6 +41,9 @@ static enum uv_system_type uv_system_typ
*/
void __init setup_apic_routing(void)
{
+ if (uv_system_type == UV_NON_UNIQUE_APIC)
+ genapic = &apic_x2apic_uv_x;
+ else
#ifdef CONFIG_ACPI
/*
* Quirk: some x86_64 machines can only use physical APIC mode
@@ -69,7 +73,16 @@ void send_IPI_self(int vector)

unsigned int get_apic_id(void)
{
- return (apic_read(APIC_ID) >> 24) & 0xFFu;
+ unsigned int id;
+

Quoted 9 lines
 +       preempt_disable();
 +       id = apic_read(APIC_ID);
 +       if (uv_system_type >= UV_X2APIC)

+ id |= __get_cpu_var(x2apic_extra_bits);
+ else
+ id = (id >> 24) & 0xFFu;;
+ preempt_enable();
+ return id;

you can not shift id here.

GET_APIC_ID will shift that again.

you apic id will be 0 for all cpu

YH

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#22 lore raw
Quoted 15 lines
Quoted 5 lines

unsigned int get_apic_id(void)
{
- return (apic_read(APIC_ID) >> 24) & 0xFFu;
+ unsigned int id;
+

Quoted 9 lines
 +       preempt_disable();
 +       id = apic_read(APIC_ID);
 +       if (uv_system_type >= UV_X2APIC)

+ id |= __get_cpu_var(x2apic_extra_bits);
+ else
+ id = (id >> 24) & 0xFFu;;
+ preempt_enable();
+ return id;

Quoted 6 lines

you can not shift id here.

GET_APIC_ID will shift that again.

you apic id will be 0 for all cpu

I think this is fixed in the patch that I submitted on Friday. I had to rework the GET_APIC_ID() changes because of the unification of -32 & -64 apic code. I think the new code is much cleaner...

--- jack

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#23 lore raw
Quoted 17 lines · Jack Steiner
Quoted 17 lines
Quoted 5 lines

unsigned int get_apic_id(void)
{
- return (apic_read(APIC_ID) >> 24) & 0xFFu;
+ unsigned int id;
+

Quoted 9 lines
 +       preempt_disable();
 +       id = apic_read(APIC_ID);
 +       if (uv_system_type >= UV_X2APIC)

+ id |= __get_cpu_var(x2apic_extra_bits);
+ else
+ id = (id >> 24) & 0xFFu;;
+ preempt_enable();
+ return id;

you can not shift id here.

Quoted 8 lines
Quoted 4 lines

GET_APIC_ID will shift that again.

you apic id will be 0 for all cpu

I think this is fixed in the patch that I submitted on Friday. I had to rework the GET_APIC_ID() changes because of the unification of -32 & -64 apic code. I think the new code is much cleaner...

i think Ingo already put you Friday's version in x86.git#latest.

that is wrong too with extra shift.

YH

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>