Skip to contentSkip to conversation

x86: fixed mtrr change WP to WB

PATCH In review Yinghai Lu 9 participants 65 messages May 6, 2008 – Jun 26, 2008 3 messages not in the archive

Subsystems (4)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Yinghai Lu

author
#1 lore raw

PATCH 1/1 x86: update mptable

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

drivers/acpi/pci_irq.c +4 -0
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -474,6 +474,8 @@ acpi_pci_irq_derive(struct pci_dev *dev,
 	return irq;
 }
 
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, u32 gsi, int triggering, int polarity);
+
 /*
  * acpi_pci_irq_enable
  * success: return 0
@@ -570,6 +572,8 @@ int acpi_pci_irq_enable(struct pci_dev *
 	       (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 	       (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq, triggering, polarity);
+
 	return 0;
 }
 
arch/x86/kernel/mpparse.c +254 -10

298 lines not on this page · raw message

author
#2 lore raw

PATCH 1/1 x86: fixed mtrr change WP to WB

[PATCH] x86: fixed mtrr change WP to WB

so we modify mptable near below 1M

arch/x86/kernel/cpu/mtrr/generic.c +20 -0
Index: linux-2.6/arch/x86/kernel/cpu/mtrr/generic.c
===================================================================
@@ -192,6 +192,26 @@ void mtrr_save_fixed_ranges(void *info)
 		get_fixed_ranges(mtrr_state.fixed_ranges);
 }
 
+int update_mtrr_fixed_ranges(unsigned char old_type, unsigned char new_type)
+{
+	unsigned char *type;
+	int i;
+	int changed = 0;
+
+	if (!mtrr_state.have_fixed)
+		return 0;
+
+	type = mtrr_state.fixed_ranges;
+	for (i = 0; i < NUM_FIXED_RANGES; i++) {
+		if (type[i] == old_type) {
+			type[i] = new_type;
+			changed = 1;
+		}
+	}
+
+	return changed;
+}
+
 static void print_fixed(unsigned base, unsigned step, const mtrr_type*types)
 {
 	unsigned i;
arch/x86/kernel/cpu/mtrr/main.c +25 -4
Index: linux-2.6/arch/x86/kernel/cpu/mtrr/main.c
===================================================================
@@ -794,6 +794,24 @@ x86_get_mtrr_mem_range(struct res_range 
 	return nr_range;
 }
 
+extern int __initdata enable_update_mptable;
+
+static int __init fixed_mtrr_cleanup(void)
+{
+	unsigned char new_type;
+
+	if (!enable_update_mptable)
+		return 0;
+
+	/* AMD 0x1e, intel 0x06 */
+	new_type = 0x06;
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+	    (boot_cpu_data.x86 >= 0x0f && boot_cpu_data.x86 <= 0x11))
+		new_type = 0x1e;
+
+	return update_mtrr_fixed_ranges(0x05, new_type);
+}
+
 static struct res_range __initdata range[RANGE_NUM];
 
 #ifdef CONFIG_MTRR_SANITIZER
@@ -1162,6 +1180,7 @@ static int __init mtrr_cleanup(unsigned 
 	unsigned long range_sums, range_sums_new;
 	int index_good;
 	int num_reg_good;
+	int changed;
 
 	/* extra one for all 0 */
 	int num[MTRR_NUM_TYPES + 1];
@@ -1173,6 +1192,8 @@ static int __init mtrr_cleanup(unsigned 
 	if (def != MTRR_TYPE_UNCACHABLE)
 		return 0;
 
+	changed = fixed_mtrr_cleanup();
+
 	/* get it and store it aside */
 	memset(range_state, 0, sizeof(range_state));
 	for (i = 0; i < num_var_ranges; i++) {
@@ -1196,12 +1217,12 @@ static int __init mtrr_cleanup(unsigned 
 
 	/* check if we got UC entries */
 	if (!num[MTRR_TYPE_UNCACHABLE])
-		return 0;
+		return changed;
 
 	/* check if we only had WB and UC */
 	if (num[MTRR_TYPE_WRBACK] + num[MTRR_TYPE_UNCACHABLE] !=
 		num_var_ranges - num[MTRR_NUM_TYPES])
-		return 0;
+		return changed;
 
 	memset(range, 0, sizeof(range));
 	extra_remove_size = 0;
@@ -1363,12 +1384,12 @@ static int __init mtrr_cleanup(unsigned 
 	printk(KERN_INFO "mtrr_cleanup: can not find optimal value\n");
 	printk(KERN_INFO "please specify mtrr_gran_size/mtrr_chunk_size\n");
 
-	return 0;
+	return changed;
 }
 #else
 static int __init mtrr_cleanup(unsigned address_bits)
 {
-	return 0;
+	return fixed_mtrr_cleanup();
 }
 #endif
 
arch/x86/kernel/cpu/mtrr/mtrr.h +1 -0
Index: linux-2.6/arch/x86/kernel/cpu/mtrr/mtrr.h
===================================================================
@@ -83,6 +83,7 @@ void set_mtrr_prepare_save(struct set_mt
 
 void fill_mtrr_var_range(unsigned int index,
 		u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi);
+int update_mtrr_fixed_ranges(unsigned char old_type, unsigned char new_type);
 void get_mtrr_state(void);
 
 extern void set_mtrr_ops(struct mtrr_ops * ops);
#3 lore raw
Quoted 5 lines · Yinghai Lu

[PATCH] x86: fixed mtrr change WP to WB

so we modify mptable near below 1M

Again:

This does not work on even the majority of all systems.

If the mptable should be modified, it should be copied to kernel memory and modified there. Modifying it in-place is both unsafe and, in general, simply will not work.

Sorry.

NAK on this whole set.

-hpa

#4 lore raw
Quoted 9 lines · H. Peter Anvin
Quoted 6 lines · Yinghai Lu

[PATCH] x86: fixed mtrr change WP to WB

so we modify mptable near below 1M

Quoted 7 lines

Again:

This does not work on even the majority of all systems.

If the mptable should be modified, it should be copied to kernel memory and
modified there. Modifying it in-place is both unsafe and, in general, simply will not work.

but

         * 1) Scan the bottom 1K for a signature
         * 2) Scan the top 1K of base RAM
         * 3) Scan the 64K of bios
         */
        if (smp_scan_config(0x0, 0x400, reserve) ||
            smp_scan_config(639 * 0x400, 0x400, reserve) ||
            smp_scan_config(0xF0000, 0x10000, reserve))
                return;

and all these areas are reserved already.

wonder if we could only modify mpf->mpf_physptr to point to another mpc and reuse mpf?

YH

#5 lore raw
Quoted 16 lines · Yinghai Lu
Quoted 4 lines

If the mptable should be modified, it should be copied to kernel memory and
modified there. Modifying it in-place is both unsafe and, in general, simply will not work.

but

         * 1) Scan the bottom 1K for a signature
         * 2) Scan the top 1K of base RAM
         * 3) Scan the 64K of bios
         */
        if (smp_scan_config(0x0, 0x400, reserve) ||
            smp_scan_config(639 * 0x400, 0x400, reserve) ||
            smp_scan_config(0xF0000, 0x10000, reserve))
                return;
Quoted 5 lines

and all these areas are reserved already.

wonder if we could only modify mpf->mpf_physptr to point to another mpc and reuse mpf?

Obviously, if you have already modified a table, you should save a pointer to it, and not rely on the kernel scanning later.

-hpa

#6 lore raw
Quoted 23 lines · H. Peter Anvin
Quoted 3 lines · Yinghai Lu
Quoted 3 lines

If the mptable should be modified, it should be copied to kernel memory

and

Quoted 17 lines
Quoted 3 lines

modified there. Modifying it in-place is both unsafe and, in general, simply will not work.

but

        * 1) Scan the bottom 1K for a signature
        * 2) Scan the top 1K of base RAM
        * 3) Scan the 64K of bios
        */
       if (smp_scan_config(0x0, 0x400, reserve) ||
           smp_scan_config(639 * 0x400, 0x400, reserve) ||
           smp_scan_config(0xF0000, 0x10000, reserve))
               return;

and all these areas are reserved already.

Quoted 7 lines
Quoted 4 lines

wonder if we could only modify mpf->mpf_physptr to point to another mpc and reuse mpf?

Obviously, if you have already modified a table, you should save a pointer
to it, and not rely on the kernel scanning later.

that modified mptable is for second kernel that is kexeced.

YH

#7 lore raw
Quoted 6 lines · Yinghai Lu
Quoted 3 lines

Obviously, if you have already modified a table, you should save a pointer
to it, and not rely on the kernel scanning later.

that modified mptable is for second kernel that is kexeced.

Then you would have to add a method to pass it into the kernel if you want it to be generally useful.

-hpa

#8 lore raw
Quoted 9 lines · H. Peter Anvin
Quoted 3 lines · Yinghai Lu
Quoted 3 lines

Obviously, if you have already modified a table, you should save a

pointer

Quoted 3 lines
Quoted 2 lines

to it, and not rely on the kernel scanning later.

Quoted 6 lines
Quoted 3 lines

that modified mptable is for second kernel that is kexeced.

Then you would have to add a method to pass it into the kernel if you want
it to be generally useful.

but how about old stock kernel in RHEL3U9?

YH

#9 lore raw
Quoted 6 lines · Yinghai Lu
Quoted 3 lines
Quoted 1 line

Then you would have to add a method to pass it into the kernel if you want
it to be generally useful.

but how about old stock kernel in RHEL3U9?

There is nothing you can do about those that will work on any platform.
If you have knowledge of the firmware you can of course break those rules.

-hpa

#10 lore raw
Quoted 11 lines · H. Peter Anvin
Quoted 5 lines · Yinghai Lu
Quoted 5 lines
Quoted 4 lines

Then you would have to add a method to pass it into the kernel if you

want

Quoted 3 lines
Quoted 2 lines

it to be generally useful.

Quoted 7 lines
Quoted 3 lines

but how about old stock kernel in RHEL3U9?

There is nothing you can do about those that will work on any platform. If
you have knowledge of the firmware you can of course break those rules.

thanks. I will try to allocate 4k page for mpc and copy the old mpc to it..., and reuse the old mpf.

YH

author
#11 lore raw

PATCH 1/1 x86: update mptable v2

In reply to Yinghai Lu

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

command line: update_mptable

v2: add alloc_mptable for mptable that can not be changed.
new command line: alloc_mptable

arch/x86/kernel/e820_64.c +29 -0
Index: linux-2.6/arch/x86/kernel/e820_64.c
===================================================================
@@ -301,6 +301,35 @@ unsigned long __init find_e820_area_size
 	return -1UL;
 
 }
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+unsigned long __init early_reserve_e820(unsigned long sizet,
+					unsigned long align)
+{
+	unsigned long start = 0, size = 0;
+	unsigned long addr;
+
+#ifdef CONFIG_X86_TRAMPOLINE
+	start = TRAMPOLINE_BASE;
+#endif
+	while (size < sizet)
+		start = find_e820_area_size(start, &size, align);
+
+	if (size < sizet)
+		return 0;
+
+	addr = start + size - sizet;
+
+	update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+
+	printk(KERN_INFO "update e820 for early_reserve_e820\n");
+	update_e820();
+
+	return addr;
+}
+
 /*
  * Find the highest page frame number we have available
  */
arch/x86/kernel/mpparse.c +346 -10

396 lines not on this page · raw message

arch/x86/kernel/setup_64.c +4 -0
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -56,6 +56,7 @@
 #include <asm/desc.h>
 #include <video/edid.h>
 #include <asm/e820.h>
+#include <asm/mpspec.h>
 #include <asm/dma.h>
 #include <asm/gart.h>
 #include <asm/mpspec.h>
@@ -372,6 +373,9 @@ void __init setup_arch(char **cmdline_p)
 	 * we are rounding upwards:
 	 */
 	end_pfn = e820_end_of_ram();
+
+	/* pre allocte 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
 	/* update e820 for memory not covered by WB MTRRs */
 	mtrr_bp_init();
 	if (mtrr_trim_uncached_memory(end_pfn)) {
drivers/acpi/pci_irq.c +3 -0
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -570,6 +570,9 @@ int acpi_pci_irq_enable(struct pci_dev *
 	       (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 	       (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+				 triggering, polarity);
+
 	return 0;
 }
 
include/asm-x86/e820_64.h +2 -0
Index: linux-2.6/include/asm-x86/e820_64.h
===================================================================
@@ -50,6 +50,8 @@ extern void update_e820(void);
 extern void reserve_early(unsigned long start, unsigned long end, char *name);
 extern void free_early(unsigned long start, unsigned long end);
 extern void early_res_to_bootmem(unsigned long start, unsigned long end);
+extern unsigned long early_reserve_e820(unsigned long sizet,
+					unsigned long align);
 
 #endif/*!__ASSEMBLY__*/
 
include/asm-x86/mpspec.h +3 -0
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
@@ -41,6 +41,7 @@ extern unsigned long mp_lapic_addr;
 
 extern void find_smp_config(void);
 extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
 
 void __cpuinit generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI
@@ -49,6 +50,8 @@ extern void mp_override_legacy_irq(u8 bu
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
 extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+				u32 gsi, int triggering, int polarity);
 #endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
#12 lore raw

PATCH 1/1 x86: update mptable v3

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

command line: update_mptable

v2: add alloc_mptable for mptable that can not be changed.
new command line: alloc_mptable
v3: adjust for patch that move some mp_xxx to acpi..., and mpc_ to mp_

arch/x86/kernel/e820_64.c +29 -0
Index: linux-2.6/arch/x86/kernel/e820_64.c
===================================================================
@@ -243,6 +243,35 @@ unsigned long __init find_e820_area_size
 	return -1UL;
 
 }
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+unsigned long __init early_reserve_e820(unsigned long sizet,
+					unsigned long align)
+{
+	unsigned long start = 0, size = 0;
+	unsigned long addr;
+
+#ifdef CONFIG_X86_TRAMPOLINE
+	start = TRAMPOLINE_BASE;
+#endif
+	while (size < sizet)
+		start = find_e820_area_size(start, &size, align);
+
+	if (size < sizet)
+		return 0;
+
+	addr = start + size - sizet;
+
+	update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+
+	printk(KERN_INFO "update e820 for early_reserve_e820\n");
+	update_e820();
+
+	return addr;
+}
+
 /*
  * Find the highest page frame number we have available
  */
arch/x86/kernel/mpparse.c +381 -17

435 lines not on this page · raw message

arch/x86/kernel/setup_64.c +4 -0
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -56,6 +56,7 @@
 #include <asm/desc.h>
 #include <video/edid.h>
 #include <asm/e820.h>
+#include <asm/mpspec.h>
 #include <asm/dma.h>
 #include <asm/gart.h>
 #include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
 	 * we are rounding upwards:
 	 */
 	end_pfn = e820_end_of_ram();
+
+	/* pre allocte 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
 	/* update e820 for memory not covered by WB MTRRs */
 	mtrr_bp_init();
 	if (mtrr_trim_uncached_memory(end_pfn)) {
drivers/acpi/pci_irq.c +3 -0
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -570,6 +570,9 @@ int acpi_pci_irq_enable(struct pci_dev *
 	       (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 	       (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+				 triggering, polarity);
+
 	return 0;
 }
 
include/asm-x86/e820_64.h +2 -0
Index: linux-2.6/include/asm-x86/e820_64.h
===================================================================
@@ -38,6 +38,8 @@ extern void finish_e820_parsing(void);
 extern void reserve_early(unsigned long start, unsigned long end, char *name);
 extern void free_early(unsigned long start, unsigned long end);
 extern void early_res_to_bootmem(unsigned long start, unsigned long end);
+extern unsigned long early_reserve_e820(unsigned long sizet,
+					unsigned long align);
 
 #endif/*!__ASSEMBLY__*/
 
include/asm-x86/mpspec.h +4 -0
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
@@ -41,6 +41,7 @@ extern unsigned long mp_lapic_addr;
 
 extern void find_smp_config(void);
 extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
 
 void __cpuinit generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI
@@ -49,6 +50,9 @@ extern void mp_override_legacy_irq(u8 bu
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
 extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+				u32 gsi, int triggering, int polarity);
 #endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
arch/x86/kernel/acpi/boot.c +22 -0
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
@@ -1152,6 +1152,28 @@ int mp_register_gsi(u32 gsi, int trigger
 	return gsi;
 }
 
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+			u32 gsi, int triggering, int polarity)
+{
+	struct mpc_config_intsrc intsrc;
+	int ioapic;
+
+	/* print the entry should happen on mptable identically */
+	intsrc.mpc_type = MP_INTSRC;
+	intsrc.mpc_irqtype = mp_INT;
+	intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+	intsrc.mpc_srcbus = number;
+	intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	ioapic = mp_find_ioapic(gsi);
+	intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+	intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+	MP_intsrc_info(&intsrc);
+
+	return 0;
+}
+
 /*
  * Parse IOAPIC related entries in MADT
  * returns 0 on success, < 0 on error
#13 lore raw

Re: [PATCH] x86: update mptable v3

Quoted 10 lines · Yinghai Lu

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

command line: update_mptable

v2: add alloc_mptable for mptable that can not be changed.
new command line: alloc_mptable
v3: adjust for patch that move some mp_xxx to acpi..., and mpc_ to mp_

-tip testing found a build failure with this patch:

arch/x86/kernel/mpparse.c: In function 'get_MP_intsrc_index':
arch/x86/kernel/mpparse.c:891: error: 'mp_irq_entries' undeclared (first use inthis function) arch/x86/kernel/mpparse.c:891: error: (Each undeclared identifier is reported only once [...]

config at:

http://redhat.com/~mingo/misc/config-Mon_May_19_17_38_13_CEST_2008.bad

Ingo

#14 lore raw

PATCH 1/1 x86: update mptable v4

In reply to Yinghai Lu

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

command line: update_mptable

v2: add alloc_mptable for mptable that can not be changed.
new command line: alloc_mptable
v3: adjust for patch that move some mp_xxx to acpi..., and mpc_ to mp_
v4: fix i386 without IO_APIC support compiling

arch/x86/kernel/e820_64.c +29 -0
Index: linux-2.6/arch/x86/kernel/e820_64.c
===================================================================
@@ -243,6 +243,35 @@ unsigned long __init find_e820_area_size
 	return -1UL;
 
 }
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+unsigned long __init early_reserve_e820(unsigned long sizet,
+					unsigned long align)
+{
+	unsigned long start = 0, size = 0;
+	unsigned long addr;
+
+#ifdef CONFIG_X86_TRAMPOLINE
+	start = TRAMPOLINE_BASE;
+#endif
+	while (size < sizet)
+		start = find_e820_area_size(start, &size, align);
+
+	if (size < sizet)
+		return 0;
+
+	addr = start + size - sizet;
+
+	update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+
+	printk(KERN_INFO "update e820 for early_reserve_e820\n");
+	update_e820();
+
+	return addr;
+}
+
 /*
  * Find the highest page frame number we have available
  */
arch/x86/kernel/mpparse.c +384 -17

438 lines not on this page · raw message

arch/x86/kernel/setup_64.c +4 -0
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -56,6 +56,7 @@
 #include <asm/desc.h>
 #include <video/edid.h>
 #include <asm/e820.h>
+#include <asm/mpspec.h>
 #include <asm/dma.h>
 #include <asm/gart.h>
 #include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
 	 * we are rounding upwards:
 	 */
 	end_pfn = e820_end_of_ram();
+
+	/* pre allocte 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
 	/* update e820 for memory not covered by WB MTRRs */
 	mtrr_bp_init();
 	if (mtrr_trim_uncached_memory(end_pfn)) {
drivers/acpi/pci_irq.c +3 -0
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -570,6 +570,9 @@ int acpi_pci_irq_enable(struct pci_dev *
 	       (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 	       (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+				 triggering, polarity);
+
 	return 0;
 }
 
include/asm-x86/e820_64.h +2 -0
Index: linux-2.6/include/asm-x86/e820_64.h
===================================================================
@@ -38,6 +38,8 @@ extern void finish_e820_parsing(void);
 extern void reserve_early(unsigned long start, unsigned long end, char *name);
 extern void free_early(unsigned long start, unsigned long end);
 extern void early_res_to_bootmem(unsigned long start, unsigned long end);
+extern unsigned long early_reserve_e820(unsigned long sizet,
+					unsigned long align);
 
 #endif/*!__ASSEMBLY__*/
 
include/asm-x86/mpspec.h +4 -0
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
@@ -41,6 +41,7 @@ extern unsigned long mp_lapic_addr;
 
 extern void find_smp_config(void);
 extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
 
 void __cpuinit generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI
@@ -49,6 +50,9 @@ extern void mp_override_legacy_irq(u8 bu
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
 extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+				u32 gsi, int triggering, int polarity);
 #endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
arch/x86/kernel/acpi/boot.c +22 -0
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
@@ -1151,6 +1151,28 @@ int mp_register_gsi(u32 gsi, int trigger
 	return gsi;
 }
 
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+			u32 gsi, int triggering, int polarity)
+{
+	struct mpc_config_intsrc intsrc;
+	int ioapic;
+
+	/* print the entry should happen on mptable identically */
+	intsrc.mpc_type = MP_INTSRC;
+	intsrc.mpc_irqtype = mp_INT;
+	intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+	intsrc.mpc_srcbus = number;
+	intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	ioapic = mp_find_ioapic(gsi);
+	intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+	intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+	MP_intsrc_info(&intsrc);
+
+	return 0;
+}
+
 /*
  * Parse IOAPIC related entries in MADT
  * returns 0 on success, < 0 on error
#15 lore raw

PATCH 1/1 x86: update mptable v5

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

command line: update_mptable

v2: add alloc_mptable for mptable that can not be changed.
new command line: alloc_mptable
v3: adjust for patch that move some mp_xxx to acpi..., and mpc_ to mp_
v4: fix i386 without IO_APIC support compiling
v5: make it could be applied after
x86: extend e820 ealy_res support 32bit

arch/x86/kernel/mpparse.c +385 -17
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
@@ -25,6 +25,7 @@
 #include <asm/proto.h>
 #include <asm/acpi.h>
 #include <asm/bios_ebda.h>
+#include <asm/e820.h>
 
 #include <mach_apic.h>
 #ifdef CONFIG_X86_32
@@ -184,20 +185,82 @@ static void __init MP_ioapic_info(struct
 	nr_ioapics++;
 }
 
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init print_MP_intsrc_info(struct mpc_config_intsrc *m)
 {
-	printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
+	printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
 		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
 		m->mpc_irqtype, m->mpc_irqflag & 3,
 		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
 		m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
-	mp_irqs[mp_irq_entries].mp_dstapic = m->mpc_dstapic;
-	mp_irqs[mp_irq_entries].mp_type = m->mpc_type;
-	mp_irqs[mp_irq_entries].mp_irqtype = m->mpc_irqtype;
-	mp_irqs[mp_irq_entries].mp_irqflag = m->mpc_irqflag;
-	mp_irqs[mp_irq_entries].mp_srcbus = m->mpc_srcbus;
-	mp_irqs[mp_irq_entries].mp_srcbusirq = m->mpc_srcbusirq;
-	mp_irqs[mp_irq_entries].mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+{
+	printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
+		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+		mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+		(mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+		mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+}
+
+static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
+				    struct mp_config_intsrc *mp_irq)
+{
+	mp_irq->mp_dstapic = m->mpc_dstapic;
+	mp_irq->mp_type = m->mpc_type;
+	mp_irq->mp_irqtype = m->mpc_irqtype;
+	mp_irq->mp_irqflag = m->mpc_irqflag;
+	mp_irq->mp_srcbus = m->mpc_srcbus;
+	mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+	mp_irq->mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+					struct mpc_config_intsrc *m)
+{
+	m->mpc_dstapic = mp_irq->mp_dstapic;
+	m->mpc_type = mp_irq->mp_type;
+	m->mpc_irqtype = mp_irq->mp_irqtype;
+	m->mpc_irqflag = mp_irq->mp_irqflag;
+	m->mpc_srcbus = mp_irq->mp_srcbus;
+	m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+	m->mpc_dstirq = mp_irq->mp_dstirq;
+}
+
+static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+					struct mpc_config_intsrc *m)
+{
+	if (mp_irq->mp_dstapic != m->mpc_dstapic)
+		return 1;
+	if (mp_irq->mp_type != m->mpc_type)
+		return 2;
+	if (mp_irq->mp_irqtype != m->mpc_irqtype)
+		return 3;
+	if (mp_irq->mp_irqflag != m->mpc_irqflag)
+		return 4;
+	if (mp_irq->mp_srcbus != m->mpc_srcbus)
+		return 5;
+	if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+		return 6;
+	if (mp_irq->mp_dstirq != m->mpc_dstirq)
+		return 7;
+
+	return 0;
+}
+
+void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+{
+	int i;
+
+	print_MP_intsrc_info(m);
+
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+			return;
+	}
+
+	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
 	if (++mp_irq_entries == MAX_IRQ_SOURCES)
 		panic("Max # of irq sources exceeded!!\n");
 }
@@ -291,12 +354,9 @@ static inline void mps_oem_check(struct 
  * Read/parse the MPC
  */
 
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+				char *str)
 {
-	char str[16];
-	char oem[10];
-	int count = sizeof(*mpc);
-	unsigned char *mpt = ((unsigned char *)mpc) + count;
 
 	if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
 		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
@@ -324,13 +384,28 @@ static int __init smp_read_mpc(struct mp
 	memcpy(str, mpc->mpc_productid, 12);
 	str[12] = 0;
 
-#ifdef CONFIG_X86_32
-	mps_oem_check(mpc, oem, str);
-#endif
 	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
 
 	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
 
+	return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+	char str[16];
+	char oem[10];
+
+	int count = sizeof(*mpc);
+	unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+	if (!smp_check_mpc(mpc, oem, str))
+		return 0;
+
+#ifdef CONFIG_X86_32
+	mps_oem_check(mpc, oem, str);
+#endif
+
 	/* save the local APIC address, it might be non-default */
 	if (!acpi_lapic)
 		mp_lapic_addr = mpc->mpc_lapic;
@@ -798,3 +873,296 @@ void __init find_smp_config(void)
 {
 	__find_smp_config(1);
 }
+
+#ifdef CONFIG_X86_IO_APIC
+static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+
+static int  __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
+{
+	int i;
+
+	if (m->mpc_irqtype != mp_INT)
+		return 0;
+
+	if (m->mpc_irqflag != 0x0f)
+		return 0;
+
+	/* not legacy */
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (mp_irqs[i].mp_irqtype != mp_INT)
+			continue;
+
+		if (mp_irqs[i].mp_irqflag != 0x0f)
+			continue;
+
+		if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
+			continue;
+		if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
+			continue;
+		if (irq_used[i]) {
+			/* already claimed */
+			return -2;
+		}
+		irq_used[i] = 1;
+		return i;
+	}
+
+	/* not found */
+	return -1;
+}
+
+#define SPARE_SLOT_NUM 20
+
+static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+#endif
+
+static int  __init replace_intsrc_all(struct mp_config_table *mpc,
+					unsigned long mpc_new_phys,
+					unsigned long mpc_new_length)
+{
+#ifdef CONFIG_X86_IO_APIC
+	int i;
+	int nr_m_spare = 0;
+#endif
+
+	int count = sizeof(*mpc);
+	unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+	printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
+	while (count < mpc->mpc_length) {
+		switch (*mpt) {
+		case MP_PROCESSOR:
+			{
+				struct mpc_config_processor *m =
+				    (struct mpc_config_processor *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		case MP_BUS:
+			{
+				struct mpc_config_bus *m =
+				    (struct mpc_config_bus *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		case MP_IOAPIC:
+			{
+				mpt += sizeof(struct mpc_config_ioapic);
+				count += sizeof(struct mpc_config_ioapic);
+				break;
+			}
+		case MP_INTSRC:
+			{
+#ifdef CONFIG_X86_IO_APIC
+				struct mpc_config_intsrc *m =
+				    (struct mpc_config_intsrc *)mpt;
+
+				printk(KERN_INFO "OLD ");
+				print_MP_intsrc_info(m);
+				i = get_MP_intsrc_index(m);
+				if (i > 0) {
+					assign_to_mpc_intsrc(&mp_irqs[i], m);
+					printk(KERN_INFO "NEW ");
+					print_mp_irq_info(&mp_irqs[i]);
+				} else if (!i) {
+					/* legacy, do nothing */
+				} else if (nr_m_spare < SPARE_SLOT_NUM) {
+					/*
+					 * not found (-1), or duplicated (-2)
+					 * are invalid entries,
+					 * we need to use the slot  later
+					 */
+					m_spare[nr_m_spare] = m;
+					nr_m_spare++;
+				}
+#endif
+				mpt += sizeof(struct mpc_config_intsrc);
+				count += sizeof(struct mpc_config_intsrc);
+				break;
+			}
+		case MP_LINTSRC:
+			{
+				struct mpc_config_lintsrc *m =
+				    (struct mpc_config_lintsrc *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		default:
+			/* wrong mptable */
+			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+			printk(KERN_ERR "type %x\n", *mpt);
+			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+					1, mpc, mpc->mpc_length, 1);
+			goto out;
+		}
+	}
+
+#ifdef CONFIG_X86_IO_APIC
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (irq_used[i])
+			continue;
+
+		if (mp_irqs[i].mp_irqtype != mp_INT)
+			continue;
+
+		if (mp_irqs[i].mp_irqflag != 0x0f)
+			continue;
+
+		if (nr_m_spare > 0) {
+			printk(KERN_INFO "*NEW* found ");
+			nr_m_spare--;
+			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+			m_spare[nr_m_spare] = NULL;
+		} else {
+			struct mpc_config_intsrc *m =
+			    (struct mpc_config_intsrc *)mpt;
+			count += sizeof(struct mpc_config_intsrc);
+			if (!mpc_new_phys) {
+				printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+			} else {
+				if (count <= mpc_new_length)
+					printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
+				else {
+					printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
+					goto out;
+				}
+			}
+			assign_to_mpc_intsrc(&mp_irqs[i], m);
+			mpc->mpc_length = count;
+			mpt += sizeof(struct mpc_config_intsrc);
+		}
+		print_mp_irq_info(&mp_irqs[i]);
+	}
+#endif
+out:
+	/* update checksum */
+	mpc->mpc_checksum = 0;
+	mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
+					   mpc->mpc_length);
+
+	return 0;
+}
+
+int __initdata enable_update_mptable;
+
+static int __init update_mptable_setup(char *str)
+{
+	enable_update_mptable = 1;
+	return 0;
+}
+early_param("update_mptable", update_mptable_setup);
+
+static unsigned long __initdata mpc_new_phys;
+static unsigned long mpc_new_length __initdata = 4096;
+
+#ifdef CONFIG_X86_64
+/* alloc_mptable or alloc_mptable=4k */
+static int __initdata alloc_mptable;
+static int __init parse_alloc_mptable_opt(char *p)
+{
+	enable_update_mptable = 1;
+	alloc_mptable = 1;
+	if (!p)
+		return 0;
+	mpc_new_length = memparse(p, &p);
+	return 0;
+}
+early_param("alloc_mptable", parse_alloc_mptable_opt);
+
+void __init early_reserve_e820_mpc_new(void)
+{
+	if (enable_update_mptable && alloc_mptable)
+		mpc_new_phys = early_reserve_e820(mpc_new_length, 4);
+}
+#else
+void __init early_reserve_e820_mpc_new(void)
+{
+}
+#endif
+
+static int __init update_mp_table(void)
+{
+	char str[16];
+	char oem[10];
+	struct intel_mp_floating *mpf;
+	struct mp_config_table *mpc;
+	struct mp_config_table *mpc_new;
+
+	if (!enable_update_mptable)
+		return 0;
+
+	mpf = mpf_found;
+	if (!mpf)
+		return 0;
+
+	/*
+	 * Now see if we need to go further.
+	 */
+	if (mpf->mpf_feature1 != 0)
+		return 0;
+
+	if (!mpf->mpf_physptr)
+		return 0;
+
+	mpc = phys_to_virt(mpf->mpf_physptr);
+
+	if (!smp_check_mpc(mpc, oem, str))
+		return 0;
+
+	printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf));
+	printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+
+	if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
+		mpc_new_phys = 0;
+		printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
+			 mpc_new_length);
+	}
+
+	if (!mpc_new_phys) {
+		unsigned char old, new;
+		/* check if we can change the postion */
+		mpc->mpc_checksum = 0;
+		old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+		mpc->mpc_checksum = 0xff;
+		new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+		if (old == new) {
+			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+			return 0;
+		}
+		printk(KERN_INFO "use in-positon replacing\n");
+	} else {
+		mpf->mpf_physptr = mpc_new_phys;
+		mpc_new = phys_to_virt(mpc_new_phys);
+		memcpy(mpc_new, mpc, mpc->mpc_length);
+		mpc = mpc_new;
+		/* check if we can modify that */
+		if (mpc_new_phys - mpf->mpf_physptr) {
+			struct intel_mp_floating *mpf_new;
+			/* steal 16 bytes from [0, 1k) */
+			printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+			mpf_new = phys_to_virt(0x400 - 16);
+			memcpy(mpf_new, mpf, 16);
+			mpf = mpf_new;
+			mpf->mpf_physptr = mpc_new_phys;
+		}
+		mpf->mpf_checksum = 0;
+		mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16);
+		printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr);
+	}
+
+	/*
+	 * only replace the one with mp_INT and
+	 *	 MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
+	 * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
+	 * may need pci=routeirq for all coverage
+	 */
+	replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);
+
+	return 0;
+}
+
+late_initcall(update_mp_table);
arch/x86/kernel/setup_64.c +4 -0
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -56,6 +56,7 @@
 #include <asm/desc.h>
 #include <video/edid.h>
 #include <asm/e820.h>
+#include <asm/mpspec.h>
 #include <asm/dma.h>
 #include <asm/gart.h>
 #include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
 	 * we are rounding upwards:
 	 */
 	end_pfn = e820_end_of_ram();
+
+	/* pre allocte 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
 	/* update e820 for memory not covered by WB MTRRs */
 	mtrr_bp_init();
 	if (mtrr_trim_uncached_memory(end_pfn)) {
drivers/acpi/pci_irq.c +3 -0
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -570,6 +570,9 @@ int acpi_pci_irq_enable(struct pci_dev *
 	       (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 	       (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+	mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+				 triggering, polarity);
+
 	return 0;
 }
 
include/asm-x86/mpspec.h +4 -0
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
@@ -41,6 +41,7 @@ extern unsigned long mp_lapic_addr;
 
 extern void find_smp_config(void);
 extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
 
 void __cpuinit generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI
@@ -49,6 +50,9 @@ extern void mp_override_legacy_irq(u8 bu
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
 extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+				u32 gsi, int triggering, int polarity);
 #endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
arch/x86/kernel/acpi/boot.c +22 -0
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
@@ -1151,6 +1151,28 @@ int mp_register_gsi(u32 gsi, int trigger
 	return gsi;
 }
 
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+			u32 gsi, int triggering, int polarity)
+{
+	struct mpc_config_intsrc intsrc;
+	int ioapic;
+
+	/* print the entry should happen on mptable identically */
+	intsrc.mpc_type = MP_INTSRC;
+	intsrc.mpc_irqtype = mp_INT;
+	intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+	intsrc.mpc_srcbus = number;
+	intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	ioapic = mp_find_ioapic(gsi);
+	intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+	intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+	MP_intsrc_info(&intsrc);
+
+	return 0;
+}
+
 /*
  * Parse IOAPIC related entries in MADT
  * returns 0 on success, < 0 on error
arch/x86/kernel/e820.c +28 -0
Index: linux-2.6/arch/x86/kernel/e820.c
===================================================================
@@ -707,3 +707,31 @@ u64 __init find_e820_area_size(u64 start
 	return -1UL;
 
 }
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+u64 __init early_reserve_e820(u64 sizet, u64 align)
+{
+	u64 start = 0, size = 0;
+	u64 addr;
+
+#ifdef CONFIG_X86_TRAMPOLINE
+	start = TRAMPOLINE_BASE;
+#endif
+	while (size < sizet)
+		start = find_e820_area_size(start, &size, align);
+
+	if (size < sizet)
+		return 0;
+
+	addr = start + size - sizet;
+
+	update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+
+	printk(KERN_INFO "update e820 for early_reserve_e820\n");
+	update_e820();
+
+	return addr;
+}
+
include/asm-x86/e820.h +1 -0
Index: linux-2.6/include/asm-x86/e820.h
===================================================================
@@ -75,6 +75,7 @@ extern u64 find_e820_area_size(u64 start
 extern void reserve_early(u64 start, u64 end, char *name);
 extern void free_early(u64 start, u64 end);
 extern void early_res_to_bootmem(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 sizet, u64 align);
 
 #endif /* __ASSEMBLY__ */
 
#16 lore raw

PATCH 1/1 x86: update mptable v6

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

command line: update_mptable

v2: add alloc_mptable for mptable that can not be changed.
new command line: alloc_mptable
v3: adjust for patch that move some mp_xxx to acpi..., and mpc_ to mp_
v4: fix i386 without IO_APIC support compiling
v5: make it could be applied after
x86: extend e820 ealy_res support 32bit
v6: 32bit support alloc_mptable too
fix ia64 compilation

arch/x86/kernel/mpparse.c +385 -17
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
@@ -25,6 +25,8 @@
 #include <asm/proto.h>
 #include <asm/acpi.h>
 #include <asm/bios_ebda.h>
+#include <asm/e820.h>
+#include <asm/trampoline.h>
 
 #include <mach_apic.h>
 #ifdef CONFIG_X86_32
@@ -161,20 +163,82 @@ static void __init MP_ioapic_info(struct
 	nr_ioapics++;
 }
 
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init print_MP_intsrc_info(struct mpc_config_intsrc *m)
 {
-	printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
+	printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
 		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
 		m->mpc_irqtype, m->mpc_irqflag & 3,
 		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
 		m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
-	mp_irqs[mp_irq_entries].mp_dstapic = m->mpc_dstapic;
-	mp_irqs[mp_irq_entries].mp_type = m->mpc_type;
-	mp_irqs[mp_irq_entries].mp_irqtype = m->mpc_irqtype;
-	mp_irqs[mp_irq_entries].mp_irqflag = m->mpc_irqflag;
-	mp_irqs[mp_irq_entries].mp_srcbus = m->mpc_srcbus;
-	mp_irqs[mp_irq_entries].mp_srcbusirq = m->mpc_srcbusirq;
-	mp_irqs[mp_irq_entries].mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+{
+	printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
+		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+		mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+		(mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+		mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+}
+
+static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
+				    struct mp_config_intsrc *mp_irq)
+{
+	mp_irq->mp_dstapic = m->mpc_dstapic;
+	mp_irq->mp_type = m->mpc_type;
+	mp_irq->mp_irqtype = m->mpc_irqtype;
+	mp_irq->mp_irqflag = m->mpc_irqflag;
+	mp_irq->mp_srcbus = m->mpc_srcbus;
+	mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+	mp_irq->mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+					struct mpc_config_intsrc *m)
+{
+	m->mpc_dstapic = mp_irq->mp_dstapic;
+	m->mpc_type = mp_irq->mp_type;
+	m->mpc_irqtype = mp_irq->mp_irqtype;
+	m->mpc_irqflag = mp_irq->mp_irqflag;
+	m->mpc_srcbus = mp_irq->mp_srcbus;
+	m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+	m->mpc_dstirq = mp_irq->mp_dstirq;
+}
+
+static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+					struct mpc_config_intsrc *m)
+{
+	if (mp_irq->mp_dstapic != m->mpc_dstapic)
+		return 1;
+	if (mp_irq->mp_type != m->mpc_type)
+		return 2;
+	if (mp_irq->mp_irqtype != m->mpc_irqtype)
+		return 3;
+	if (mp_irq->mp_irqflag != m->mpc_irqflag)
+		return 4;
+	if (mp_irq->mp_srcbus != m->mpc_srcbus)
+		return 5;
+	if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+		return 6;
+	if (mp_irq->mp_dstirq != m->mpc_dstirq)
+		return 7;
+
+	return 0;
+}
+
+void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+{
+	int i;
+
+	print_MP_intsrc_info(m);
+
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+			return;
+	}
+
+	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
 	if (++mp_irq_entries == MAX_IRQ_SOURCES)
 		panic("Max # of irq sources exceeded!!\n");
 }
@@ -268,12 +332,9 @@ static inline void mps_oem_check(struct 
  * Read/parse the MPC
  */
 
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+				char *str)
 {
-	char str[16];
-	char oem[10];
-	int count = sizeof(*mpc);
-	unsigned char *mpt = ((unsigned char *)mpc) + count;
 
 	if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
 		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
@@ -301,13 +362,28 @@ static int __init smp_read_mpc(struct mp
 	memcpy(str, mpc->mpc_productid, 12);
 	str[12] = 0;
 
-#ifdef CONFIG_X86_32
-	mps_oem_check(mpc, oem, str);
-#endif
 	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
 
 	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
 
+	return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+	char str[16];
+	char oem[10];
+
+	int count = sizeof(*mpc);
+	unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+	if (!smp_check_mpc(mpc, oem, str))
+		return 0;
+
+#ifdef CONFIG_X86_32
+	mps_oem_check(mpc, oem, str);
+#endif
+
 	/* save the local APIC address, it might be non-default */
 	if (!acpi_lapic)
 		mp_lapic_addr = mpc->mpc_lapic;
@@ -785,3 +861,295 @@ void __init find_smp_config(void)
 {
 	__find_smp_config(1);
 }
+
+#ifdef CONFIG_X86_IO_APIC
+static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+
+static int  __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
+{
+	int i;
+
+	if (m->mpc_irqtype != mp_INT)
+		return 0;
+
+	if (m->mpc_irqflag != 0x0f)
+		return 0;
+
+	/* not legacy */
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (mp_irqs[i].mp_irqtype != mp_INT)
+			continue;
+
+		if (mp_irqs[i].mp_irqflag != 0x0f)
+			continue;
+
+		if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
+			continue;
+		if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
+			continue;
+		if (irq_used[i]) {
+			/* already claimed */
+			return -2;
+		}
+		irq_used[i] = 1;
+		return i;
+	}
+
+	/* not found */
+	return -1;
+}
+
+#define SPARE_SLOT_NUM 20
+
+static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+#endif
+
+static int  __init replace_intsrc_all(struct mp_config_table *mpc,
+					unsigned long mpc_new_phys,
+					unsigned long mpc_new_length)
+{
+#ifdef CONFIG_X86_IO_APIC
+	int i;
+	int nr_m_spare = 0;
+#endif
+
+	int count = sizeof(*mpc);
+	unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+	printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
+	while (count < mpc->mpc_length) {
+		switch (*mpt) {
+		case MP_PROCESSOR:
+			{
+				struct mpc_config_processor *m =
+				    (struct mpc_config_processor *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		case MP_BUS:
+			{
+				struct mpc_config_bus *m =
+				    (struct mpc_config_bus *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		case MP_IOAPIC:
+			{
+				mpt += sizeof(struct mpc_config_ioapic);
+				count += sizeof(struct mpc_config_ioapic);
+				break;
+			}
+		case MP_INTSRC:
+			{
+#ifdef CONFIG_X86_IO_APIC
+				struct mpc_config_intsrc *m =
+				    (struct mpc_config_intsrc *)mpt;
+
+				printk(KERN_INFO "OLD ");
+				print_MP_intsrc_info(m);
+				i = get_MP_intsrc_index(m);
+				if (i > 0) {
+					assign_to_mpc_intsrc(&mp_irqs[i], m);
+					printk(KERN_INFO "NEW ");
+					print_mp_irq_info(&mp_irqs[i]);
+				} else if (!i) {
+					/* legacy, do nothing */
+				} else if (nr_m_spare < SPARE_SLOT_NUM) {
+					/*
+					 * not found (-1), or duplicated (-2)
+					 * are invalid entries,
+					 * we need to use the slot  later
+					 */
+					m_spare[nr_m_spare] = m;
+					nr_m_spare++;
+				}
+#endif
+				mpt += sizeof(struct mpc_config_intsrc);
+				count += sizeof(struct mpc_config_intsrc);
+				break;
+			}
+		case MP_LINTSRC:
+			{
+				struct mpc_config_lintsrc *m =
+				    (struct mpc_config_lintsrc *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		default:
+			/* wrong mptable */
+			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+			printk(KERN_ERR "type %x\n", *mpt);
+			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+					1, mpc, mpc->mpc_length, 1);
+			goto out;
+		}
+	}
+
+#ifdef CONFIG_X86_IO_APIC
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (irq_used[i])
+			continue;
+
+		if (mp_irqs[i].mp_irqtype != mp_INT)
+			continue;
+
+		if (mp_irqs[i].mp_irqflag != 0x0f)
+			continue;
+
+		if (nr_m_spare > 0) {
+			printk(KERN_INFO "*NEW* found ");
+			nr_m_spare--;
+			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+			m_spare[nr_m_spare] = NULL;
+		} else {
+			struct mpc_config_intsrc *m =
+			    (struct mpc_config_intsrc *)mpt;
+			count += sizeof(struct mpc_config_intsrc);
+			if (!mpc_new_phys) {
+				printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+			} else {
+				if (count <= mpc_new_length)
+					printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
+				else {
+					printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
+					goto out;
+				}
+			}
+			assign_to_mpc_intsrc(&mp_irqs[i], m);
+			mpc->mpc_length = count;
+			mpt += sizeof(struct mpc_config_intsrc);
+		}
+		print_mp_irq_info(&mp_irqs[i]);
+	}
+#endif
+out:
+	/* update checksum */
+	mpc->mpc_checksum = 0;
+	mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
+					   mpc->mpc_length);
+
+	return 0;
+}
+
+int __initdata enable_update_mptable;
+
+static int __init update_mptable_setup(char *str)
+{
+	enable_update_mptable = 1;
+	return 0;
+}
+early_param("update_mptable", update_mptable_setup);
+
+static unsigned long __initdata mpc_new_phys;
+static unsigned long mpc_new_length __initdata = 4096;
+
+/* alloc_mptable or alloc_mptable=4k */
+static int __initdata alloc_mptable;
+static int __init parse_alloc_mptable_opt(char *p)
+{
+	enable_update_mptable = 1;
+	alloc_mptable = 1;
+	if (!p)
+		return 0;
+	mpc_new_length = memparse(p, &p);
+	return 0;
+}
+early_param("alloc_mptable", parse_alloc_mptable_opt);
+
+void __init early_reserve_e820_mpc_new(void)
+{
+	if (enable_update_mptable && alloc_mptable) {
+		u64 startt = 0;
+#ifdef CONFIG_X86_TRAMPOLINE
+		startt = TRAMPOLINE_BASE;
+#endif
+		mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4);
+	}
+}
+
+static int __init update_mp_table(void)
+{
+	char str[16];
+	char oem[10];
+	struct intel_mp_floating *mpf;
+	struct mp_config_table *mpc;
+	struct mp_config_table *mpc_new;
+
+	if (!enable_update_mptable)
+		return 0;
+
+	mpf = mpf_found;
+	if (!mpf)
+		return 0;
+
+	/*
+	 * Now see if we need to go further.
+	 */
+	if (mpf->mpf_feature1 != 0)
+		return 0;
+
+	if (!mpf->mpf_physptr)
+		return 0;
+
+	mpc = phys_to_virt(mpf->mpf_physptr);
+
+	if (!smp_check_mpc(mpc, oem, str))
+		return 0;
+
+	printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf));
+	printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+
+	if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
+		mpc_new_phys = 0;
+		printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
+			 mpc_new_length);
+	}
+
+	if (!mpc_new_phys) {
+		unsigned char old, new;
+		/* check if we can change the postion */
+		mpc->mpc_checksum = 0;
+		old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+		mpc->mpc_checksum = 0xff;
+		new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+		if (old == new) {
+			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+			return 0;
+		}
+		printk(KERN_INFO "use in-positon replacing\n");
+	} else {
+		mpf->mpf_physptr = mpc_new_phys;
+		mpc_new = phys_to_virt(mpc_new_phys);
+		memcpy(mpc_new, mpc, mpc->mpc_length);
+		mpc = mpc_new;
+		/* check if we can modify that */
+		if (mpc_new_phys - mpf->mpf_physptr) {
+			struct intel_mp_floating *mpf_new;
+			/* steal 16 bytes from [0, 1k) */
+			printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+			mpf_new = phys_to_virt(0x400 - 16);
+			memcpy(mpf_new, mpf, 16);
+			mpf = mpf_new;
+			mpf->mpf_physptr = mpc_new_phys;
+		}
+		mpf->mpf_checksum = 0;
+		mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16);
+		printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr);
+	}
+
+	/*
+	 * only replace the one with mp_INT and
+	 *	 MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
+	 * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
+	 * may need pci=routeirq for all coverage
+	 */
+	replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);
+
+	return 0;
+}
+
+late_initcall(update_mp_table);
arch/x86/kernel/setup_64.c +4 -0
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -56,6 +56,7 @@
 #include <asm/desc.h>
 #include <video/edid.h>
 #include <asm/e820.h>
+#include <asm/mpspec.h>
 #include <asm/dma.h>
 #include <asm/gart.h>
 #include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
 	 * we are rounding upwards:
 	 */
 	end_pfn = e820_end_of_ram();
+
+	/* pre allocte 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
 	/* update e820 for memory not covered by WB MTRRs */
 	mtrr_bp_init();
 	if (mtrr_trim_uncached_memory(end_pfn)) {
drivers/acpi/pci_irq.c +5 -0
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -570,6 +570,11 @@ int acpi_pci_irq_enable(struct pci_dev *
 	       (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 	       (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+#ifdef CONFIG_X86
+	mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+				 triggering, polarity);
+#endif
+
 	return 0;
 }
 
include/asm-x86/mpspec.h +4 -0
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
@@ -39,6 +39,7 @@ extern unsigned long mp_lapic_addr;
 
 extern void find_smp_config(void);
 extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
 
 void __cpuinit generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI
@@ -47,6 +48,9 @@ extern void mp_override_legacy_irq(u8 bu
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
 extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+				u32 gsi, int triggering, int polarity);
 #endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
arch/x86/kernel/acpi/boot.c +22 -0
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
@@ -1164,6 +1164,28 @@ int mp_register_gsi(u32 gsi, int trigger
 	return gsi;
 }
 
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+			u32 gsi, int triggering, int polarity)
+{
+	struct mpc_config_intsrc intsrc;
+	int ioapic;
+
+	/* print the entry should happen on mptable identically */
+	intsrc.mpc_type = MP_INTSRC;
+	intsrc.mpc_irqtype = mp_INT;
+	intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+	intsrc.mpc_srcbus = number;
+	intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	ioapic = mp_find_ioapic(gsi);
+	intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+	intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+	MP_intsrc_info(&intsrc);
+
+	return 0;
+}
+
 /*
  * Parse IOAPIC related entries in MADT
  * returns 0 on success, < 0 on error
arch/x86/kernel/e820.c +25 -0
Index: linux-2.6/arch/x86/kernel/e820.c
===================================================================
@@ -739,3 +739,28 @@ u64 __init find_e820_area_size(u64 start
 	return -1UL;
 
 }
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
+{
+	u64 size = 0;
+	u64 addr;
+	u64 start;
+
+	start = startt;
+	while (size < sizet)
+		start = find_e820_area_size(start, &size, align);
+
+	if (size < sizet)
+		return 0;
+
+	addr = round_down(start + size - sizet, align);
+	update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+	printk(KERN_INFO "update e820 for early_reserve_e820\n");
+	update_e820();
+
+	return addr;
+}
+
include/asm-x86/e820.h +1 -0
Index: linux-2.6/include/asm-x86/e820.h
===================================================================
@@ -84,6 +84,7 @@ extern u64 find_e820_area_size(u64 start
 extern void reserve_early(u64 start, u64 end, char *name);
 extern void free_early(u64 start, u64 end);
 extern void early_res_to_bootmem(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
 
 #endif /* __ASSEMBLY__ */
 
#17 lore raw

PATCH 1/1 x86: update mptable v7

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

command line: update_mptable

v2: add alloc_mptable for mptable that can not be changed.
new command line: alloc_mptable
v3: adjust for patch that move some mp_xxx to acpi..., and mpc_ to mp_
v4: fix i386 without IO_APIC support compiling
v5: make it could be applied after
x86: extend e820 ealy_res support 32bit
v6: 32bit support alloc_mptable too
fix ia64 compilation
v7: fix driver in module to call mp_config_acpi_gsi

arch/x86/kernel/mpparse.c +384 -17
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
@@ -25,6 +25,8 @@
 #include <asm/proto.h>
 #include <asm/acpi.h>
 #include <asm/bios_ebda.h>
+#include <asm/e820.h>
+#include <asm/trampoline.h>
 
 #include <mach_apic.h>
 #ifdef CONFIG_X86_32
@@ -161,20 +163,81 @@ static void __init MP_ioapic_info(struct
 	nr_ioapics++;
 }
 
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void print_MP_intsrc_info(struct mpc_config_intsrc *m)
 {
-	printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
+	printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
 		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
 		m->mpc_irqtype, m->mpc_irqflag & 3,
 		(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
 		m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
-	mp_irqs[mp_irq_entries].mp_dstapic = m->mpc_dstapic;
-	mp_irqs[mp_irq_entries].mp_type = m->mpc_type;
-	mp_irqs[mp_irq_entries].mp_irqtype = m->mpc_irqtype;
-	mp_irqs[mp_irq_entries].mp_irqflag = m->mpc_irqflag;
-	mp_irqs[mp_irq_entries].mp_srcbus = m->mpc_srcbus;
-	mp_irqs[mp_irq_entries].mp_srcbusirq = m->mpc_srcbusirq;
-	mp_irqs[mp_irq_entries].mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+{
+	printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
+		" IRQ %02x, APIC ID %x, APIC INT %02x\n",
+		mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+		(mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+		mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+}
+
+static void assign_to_mp_irq(struct mpc_config_intsrc *m,
+				    struct mp_config_intsrc *mp_irq)
+{
+	mp_irq->mp_dstapic = m->mpc_dstapic;
+	mp_irq->mp_type = m->mpc_type;
+	mp_irq->mp_irqtype = m->mpc_irqtype;
+	mp_irq->mp_irqflag = m->mpc_irqflag;
+	mp_irq->mp_srcbus = m->mpc_srcbus;
+	mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+	mp_irq->mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+					struct mpc_config_intsrc *m)
+{
+	m->mpc_dstapic = mp_irq->mp_dstapic;
+	m->mpc_type = mp_irq->mp_type;
+	m->mpc_irqtype = mp_irq->mp_irqtype;
+	m->mpc_irqflag = mp_irq->mp_irqflag;
+	m->mpc_srcbus = mp_irq->mp_srcbus;
+	m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+	m->mpc_dstirq = mp_irq->mp_dstirq;
+}
+
+static int mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+					struct mpc_config_intsrc *m)
+{
+	if (mp_irq->mp_dstapic != m->mpc_dstapic)
+		return 1;
+	if (mp_irq->mp_type != m->mpc_type)
+		return 2;
+	if (mp_irq->mp_irqtype != m->mpc_irqtype)
+		return 3;
+	if (mp_irq->mp_irqflag != m->mpc_irqflag)
+		return 4;
+	if (mp_irq->mp_srcbus != m->mpc_srcbus)
+		return 5;
+	if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+		return 6;
+	if (mp_irq->mp_dstirq != m->mpc_dstirq)
+		return 7;
+
+	return 0;
+}
+
+void MP_intsrc_info(struct mpc_config_intsrc *m)
+{
+	int i;
+
+	print_MP_intsrc_info(m);
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+			return;
+	}
+
+	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
 	if (++mp_irq_entries == MAX_IRQ_SOURCES)
 		panic("Max # of irq sources exceeded!!\n");
 }
@@ -268,12 +331,9 @@ static inline void mps_oem_check(struct 
  * Read/parse the MPC
  */
 
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+				char *str)
 {
-	char str[16];
-	char oem[10];
-	int count = sizeof(*mpc);
-	unsigned char *mpt = ((unsigned char *)mpc) + count;
 
 	if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
 		printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
@@ -301,13 +361,28 @@ static int __init smp_read_mpc(struct mp
 	memcpy(str, mpc->mpc_productid, 12);
 	str[12] = 0;
 
-#ifdef CONFIG_X86_32
-	mps_oem_check(mpc, oem, str);
-#endif
 	printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
 
 	printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
 
+	return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+	char str[16];
+	char oem[10];
+
+	int count = sizeof(*mpc);
+	unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+	if (!smp_check_mpc(mpc, oem, str))
+		return 0;
+
+#ifdef CONFIG_X86_32
+	mps_oem_check(mpc, oem, str);
+#endif
+
 	/* save the local APIC address, it might be non-default */
 	if (!acpi_lapic)
 		mp_lapic_addr = mpc->mpc_lapic;
@@ -785,3 +860,295 @@ void __init find_smp_config(void)
 {
 	__find_smp_config(1);
 }
+
+#ifdef CONFIG_X86_IO_APIC
+static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+
+static int  __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
+{
+	int i;
+
+	if (m->mpc_irqtype != mp_INT)
+		return 0;
+
+	if (m->mpc_irqflag != 0x0f)
+		return 0;
+
+	/* not legacy */
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (mp_irqs[i].mp_irqtype != mp_INT)
+			continue;
+
+		if (mp_irqs[i].mp_irqflag != 0x0f)
+			continue;
+
+		if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
+			continue;
+		if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
+			continue;
+		if (irq_used[i]) {
+			/* already claimed */
+			return -2;
+		}
+		irq_used[i] = 1;
+		return i;
+	}
+
+	/* not found */
+	return -1;
+}
+
+#define SPARE_SLOT_NUM 20
+
+static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+#endif
+
+static int  __init replace_intsrc_all(struct mp_config_table *mpc,
+					unsigned long mpc_new_phys,
+					unsigned long mpc_new_length)
+{
+#ifdef CONFIG_X86_IO_APIC
+	int i;
+	int nr_m_spare = 0;
+#endif
+
+	int count = sizeof(*mpc);
+	unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+	printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
+	while (count < mpc->mpc_length) {
+		switch (*mpt) {
+		case MP_PROCESSOR:
+			{
+				struct mpc_config_processor *m =
+				    (struct mpc_config_processor *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		case MP_BUS:
+			{
+				struct mpc_config_bus *m =
+				    (struct mpc_config_bus *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		case MP_IOAPIC:
+			{
+				mpt += sizeof(struct mpc_config_ioapic);
+				count += sizeof(struct mpc_config_ioapic);
+				break;
+			}
+		case MP_INTSRC:
+			{
+#ifdef CONFIG_X86_IO_APIC
+				struct mpc_config_intsrc *m =
+				    (struct mpc_config_intsrc *)mpt;
+
+				printk(KERN_INFO "OLD ");
+				print_MP_intsrc_info(m);
+				i = get_MP_intsrc_index(m);
+				if (i > 0) {
+					assign_to_mpc_intsrc(&mp_irqs[i], m);
+					printk(KERN_INFO "NEW ");
+					print_mp_irq_info(&mp_irqs[i]);
+				} else if (!i) {
+					/* legacy, do nothing */
+				} else if (nr_m_spare < SPARE_SLOT_NUM) {
+					/*
+					 * not found (-1), or duplicated (-2)
+					 * are invalid entries,
+					 * we need to use the slot  later
+					 */
+					m_spare[nr_m_spare] = m;
+					nr_m_spare++;
+				}
+#endif
+				mpt += sizeof(struct mpc_config_intsrc);
+				count += sizeof(struct mpc_config_intsrc);
+				break;
+			}
+		case MP_LINTSRC:
+			{
+				struct mpc_config_lintsrc *m =
+				    (struct mpc_config_lintsrc *)mpt;
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+		default:
+			/* wrong mptable */
+			printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+			printk(KERN_ERR "type %x\n", *mpt);
+			print_hex_dump(KERN_ERR, "  ", DUMP_PREFIX_ADDRESS, 16,
+					1, mpc, mpc->mpc_length, 1);
+			goto out;
+		}
+	}
+
+#ifdef CONFIG_X86_IO_APIC
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (irq_used[i])
+			continue;
+
+		if (mp_irqs[i].mp_irqtype != mp_INT)
+			continue;
+
+		if (mp_irqs[i].mp_irqflag != 0x0f)
+			continue;
+
+		if (nr_m_spare > 0) {
+			printk(KERN_INFO "*NEW* found ");
+			nr_m_spare--;
+			assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+			m_spare[nr_m_spare] = NULL;
+		} else {
+			struct mpc_config_intsrc *m =
+			    (struct mpc_config_intsrc *)mpt;
+			count += sizeof(struct mpc_config_intsrc);
+			if (!mpc_new_phys) {
+				printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+			} else {
+				if (count <= mpc_new_length)
+					printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
+				else {
+					printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
+					goto out;
+				}
+			}
+			assign_to_mpc_intsrc(&mp_irqs[i], m);
+			mpc->mpc_length = count;
+			mpt += sizeof(struct mpc_config_intsrc);
+		}
+		print_mp_irq_info(&mp_irqs[i]);
+	}
+#endif
+out:
+	/* update checksum */
+	mpc->mpc_checksum = 0;
+	mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
+					   mpc->mpc_length);
+
+	return 0;
+}
+
+int __initdata enable_update_mptable;
+
+static int __init update_mptable_setup(char *str)
+{
+	enable_update_mptable = 1;
+	return 0;
+}
+early_param("update_mptable", update_mptable_setup);
+
+static unsigned long __initdata mpc_new_phys;
+static unsigned long mpc_new_length __initdata = 4096;
+
+/* alloc_mptable or alloc_mptable=4k */
+static int __initdata alloc_mptable;
+static int __init parse_alloc_mptable_opt(char *p)
+{
+	enable_update_mptable = 1;
+	alloc_mptable = 1;
+	if (!p)
+		return 0;
+	mpc_new_length = memparse(p, &p);
+	return 0;
+}
+early_param("alloc_mptable", parse_alloc_mptable_opt);
+
+void __init early_reserve_e820_mpc_new(void)
+{
+	if (enable_update_mptable && alloc_mptable) {
+		u64 startt = 0;
+#ifdef CONFIG_X86_TRAMPOLINE
+		startt = TRAMPOLINE_BASE;
+#endif
+		mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4);
+	}
+}
+
+static int __init update_mp_table(void)
+{
+	char str[16];
+	char oem[10];
+	struct intel_mp_floating *mpf;
+	struct mp_config_table *mpc;
+	struct mp_config_table *mpc_new;
+
+	if (!enable_update_mptable)
+		return 0;
+
+	mpf = mpf_found;
+	if (!mpf)
+		return 0;
+
+	/*
+	 * Now see if we need to go further.
+	 */
+	if (mpf->mpf_feature1 != 0)
+		return 0;
+
+	if (!mpf->mpf_physptr)
+		return 0;
+
+	mpc = phys_to_virt(mpf->mpf_physptr);
+
+	if (!smp_check_mpc(mpc, oem, str))
+		return 0;
+
+	printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf));
+	printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+
+	if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
+		mpc_new_phys = 0;
+		printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
+			 mpc_new_length);
+	}
+
+	if (!mpc_new_phys) {
+		unsigned char old, new;
+		/* check if we can change the postion */
+		mpc->mpc_checksum = 0;
+		old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+		mpc->mpc_checksum = 0xff;
+		new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+		if (old == new) {
+			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+			return 0;
+		}
+		printk(KERN_INFO "use in-positon replacing\n");
+	} else {
+		mpf->mpf_physptr = mpc_new_phys;
+		mpc_new = phys_to_virt(mpc_new_phys);
+		memcpy(mpc_new, mpc, mpc->mpc_length);
+		mpc = mpc_new;
+		/* check if we can modify that */
+		if (mpc_new_phys - mpf->mpf_physptr) {
+			struct intel_mp_floating *mpf_new;
+			/* steal 16 bytes from [0, 1k) */
+			printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+			mpf_new = phys_to_virt(0x400 - 16);
+			memcpy(mpf_new, mpf, 16);
+			mpf = mpf_new;
+			mpf->mpf_physptr = mpc_new_phys;
+		}
+		mpf->mpf_checksum = 0;
+		mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16);
+		printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr);
+	}
+
+	/*
+	 * only replace the one with mp_INT and
+	 *	 MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
+	 * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
+	 * may need pci=routeirq for all coverage
+	 */
+	replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);
+
+	return 0;
+}
+
+late_initcall(update_mp_table);
arch/x86/kernel/setup_64.c +4 -0
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -56,6 +56,7 @@
 #include <asm/desc.h>
 #include <video/edid.h>
 #include <asm/e820.h>
+#include <asm/mpspec.h>
 #include <asm/dma.h>
 #include <asm/gart.h>
 #include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
 	 * we are rounding upwards:
 	 */
 	end_pfn = e820_end_of_ram();
+
+	/* pre allocte 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
 	/* update e820 for memory not covered by WB MTRRs */
 	mtrr_bp_init();
 	if (mtrr_trim_uncached_memory(end_pfn)) {
drivers/acpi/pci_irq.c +5 -0
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
@@ -570,6 +570,11 @@ int acpi_pci_irq_enable(struct pci_dev *
 	       (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
 	       (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
 
+#ifdef CONFIG_X86
+	mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+				 triggering, polarity);
+#endif
+
 	return 0;
 }
 
include/asm-x86/mpspec.h +4 -0
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
@@ -39,6 +39,7 @@ extern unsigned long mp_lapic_addr;
 
 extern void find_smp_config(void);
 extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
 
 void __cpuinit generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI
@@ -47,6 +48,9 @@ extern void mp_override_legacy_irq(u8 bu
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
 extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+				u32 gsi, int triggering, int polarity);
 #endif /* CONFIG_ACPI */
 
 #define PHYSID_ARRAY_SIZE	BITS_TO_LONGS(MAX_APICS)
arch/x86/kernel/acpi/boot.c +22 -0
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
@@ -1164,6 +1164,28 @@ int mp_register_gsi(u32 gsi, int trigger
 	return gsi;
 }
 
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+			u32 gsi, int triggering, int polarity)
+{
+	struct mpc_config_intsrc intsrc;
+	int ioapic;
+
+	/* print the entry should happen on mptable identically */
+	intsrc.mpc_type = MP_INTSRC;
+	intsrc.mpc_irqtype = mp_INT;
+	intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+	intsrc.mpc_srcbus = number;
+	intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	ioapic = mp_find_ioapic(gsi);
+	intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+	intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+	MP_intsrc_info(&intsrc);
+
+	return 0;
+}
+
 /*
  * Parse IOAPIC related entries in MADT
  * returns 0 on success, < 0 on error
arch/x86/kernel/e820.c +25 -0
Index: linux-2.6/arch/x86/kernel/e820.c
===================================================================
@@ -739,3 +739,28 @@ u64 __init find_e820_area_size(u64 start
 	return -1UL;
 
 }
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
+{
+	u64 size = 0;
+	u64 addr;
+	u64 start;
+
+	start = startt;
+	while (size < sizet)
+		start = find_e820_area_size(start, &size, align);
+
+	if (size < sizet)
+		return 0;
+
+	addr = round_down(start + size - sizet, align);
+	update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+	printk(KERN_INFO "update e820 for early_reserve_e820\n");
+	update_e820();
+
+	return addr;
+}
+
include/asm-x86/e820.h +1 -0
Index: linux-2.6/include/asm-x86/e820.h
===================================================================
@@ -84,6 +84,7 @@ extern u64 find_e820_area_size(u64 start
 extern void reserve_early(u64 start, u64 end, char *name);
 extern void free_early(u64 start, u64 end);
 extern void early_res_to_bootmem(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
 
 #endif /* __ASSEMBLY__ */
 
#18 lore raw

PATCH 1/1 x86: update mptable v7 - fix

[PATCH] x86: update mptable v7 - fix

need to call early_reserve_e820 to prelocate mptable for 32bit

arch/x86/kernel/setup_32.c +2 -0
Index: linux-2.6/arch/x86/kernel/setup_32.c
===================================================================
@@ -761,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	max_pfn = e820_end_of_ram();
 
+	/* pre allocte 4k for mptable mpc */
+	early_reserve_e820_mpc_new();
 	/* update e820 for memory not covered by WB MTRRs */
 	mtrr_bp_init();
 	if (mtrr_trim_uncached_memory(max_pfn)) {
#19 lore raw

Re: [PATCH] x86: update mptable v7 - fix

Quoted 11 lines · Yinghai Lu

[PATCH] x86: update mptable v7 - fix

need to call early_reserve_e820 to prelocate mptable for 32bit

Index: linux-2.6/arch/x86/kernel/setup_32.c
===================================================================

arch/x86/kernel/setup_32.c void __init setup_arch(char **cmdline_p) · line 765

Quoted 5 lines
arch/x86/kernel/setup_32.c +2 -0
@@ -761,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	max_pfn = e820_end_of_ram();
 
+	/* pre allocte 4k for mptable mpc */
+	early_reserve_e820_mpc_new();

applied, thanks. It needed the small build fix below as well, for UP 32-bit.

Ingo

--------------->
commit 3c803fb3e1972566f7a1613f53f7e5a70fbde83f

Author: Ingo Molnar <[email protected]>
Date:   Sun May 25 21:16:06 2008 +0200

x86, mpparse: build fix

fix:

LD .tmp_vmlinux1
arch/x86/kernel/built-in.o: In function `setup_arch':
: undefined reference to `early_reserve_e820_mpc_new'

include/asm-x86/mpspec.h +4 -0
index 6e9c958..b8ba374 100644
@@ -46,7 +46,11 @@ extern unsigned long mp_lapic_addr;
 
 extern void find_smp_config(void);
 extern void get_smp_config(void);
+#ifdef CONFIG_X86_MPPARSE
 extern void early_reserve_e820_mpc_new(void);
+#else
+static inline void early_reserve_e820_mpc_new(void) { }
+#endif
 
 void __cpuinit generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI
#20 lore raw

Re: [PATCH] x86: update mptable v7 - fix

Quoted 46 lines · Ingo Molnar
Quoted 11 lines · Yinghai Lu

[PATCH] x86: update mptable v7 - fix

need to call early_reserve_e820 to prelocate mptable for 32bit

Index: linux-2.6/arch/x86/kernel/setup_32.c
===================================================================

arch/x86/kernel/setup_32.c void __init setup_arch(char **cmdline_p) · line 765

Quoted 5 lines
arch/x86/kernel/setup_32.c +2 -0
@@ -761,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
       */
      max_pfn = e820_end_of_ram();
 
+     /* pre allocte 4k for mptable mpc */
+     early_reserve_e820_mpc_new();

applied, thanks. It needed the small build fix below as well, for UP 32-bit.

Ingo

--------------->
commit 3c803fb3e1972566f7a1613f53f7e5a70fbde83f

Author: Ingo Molnar <[email protected]>
Date:   Sun May 25 21:16:06 2008 +0200

x86, mpparse: build fix

fix:

LD .tmp_vmlinux1
arch/x86/kernel/built-in.o: In function `setup_arch':
: undefined reference to `early_reserve_e820_mpc_new'

include/asm-x86/mpspec.h +0 -0
index 6e9c958..b8ba374 100644
@@ -46,7 +46,11 @@ extern unsigned long mp_lapic_addr;
 

include/asm-x86/mpspec.h extern unsigned long mp_lapic_addr; · line 56

Quoted 10 lines
include/asm-x86/mpspec.h +4 -0
 extern void find_smp_config(void);
 extern void get_smp_config(void);
+#ifdef CONFIG_X86_MPPARSE
 extern void early_reserve_e820_mpc_new(void);
+#else
+static inline void early_reserve_e820_mpc_new(void) { }
+#endif
 
 void __cpuinit generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI

thanks. So X86_MPPARSE is not needed when SMP is not enabled?

YH

#21 lore raw

Re: [PATCH] x86: update mptable v7 - fix

Quoted 1 line · Yinghai Lu

thanks. So X86_MPPARSE is not needed when SMP is not enabled?

X86_MPPARSE should depend on X86_LOCAL_APIC and you can still have it
enabled while !SMP. I think current dependencies express it quite clearly.

Maciej

#22 lore raw

Re: [PATCH] x86: update mptable v7 - fix

In reply to Yinghai Lu
Quoted 1 line · Yinghai Lu

thanks. So X86_MPPARSE is not needed when SMP is not enabled?

here's the condition:

config X86_MPPARSE

        def_bool y
        depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64

64-bit has it unconditionally, 32-bit has it on SMP, UP-IOAPIC or UP-local-APIC mode. [ (and VISWS is an ugly complication we should try to eradicate similarly to NUMAQ, if possible :-) ]

Ingo

#23 lore raw

Re: [PATCH] x86: update mptable v7 - fix

Quoted 7 lines · Ingo Molnar
Quoted 1 line · Yinghai Lu

thanks. So X86_MPPARSE is not needed when SMP is not enabled?

here's the condition:

Quoted 7 lines

config X86_MPPARSE

       def_bool y
       depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64

64-bit has it unconditionally, 32-bit has it on SMP, UP-IOAPIC or UP-local-APIC mode. [ (and VISWS is an ugly complication we should try to eradicate similarly to NUMAQ, if possible :-) ]

VISWS or VOYAGER depends on !PCI, that is some odd system.

YH

#24 lore raw

Re: [PATCH] x86: update mptable v7 - fix

Quoted 3 lines · Yinghai Lu

VISWS or VOYAGER depends on !PCI, that is some odd system.

Both are long-since obsolete systems.

-hpa

#25 lore raw

Re: [PATCH] x86: update mptable v7 - fix

In reply to Ingo Molnar
Quoted 9 lines · Ingo Molnar

here's the condition:

config X86_MPPARSE

        def_bool y
        depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64

64-bit has it unconditionally, 32-bit has it on SMP, UP-IOAPIC or UP-local-APIC mode. [ (and VISWS is an ugly complication we should try to eradicate similarly to NUMAQ, if possible :-) ]

Given X86_64 selects X86_LOCAL_APIC I am not sure the redundancy seen
above does not actually obscure the logic behind... I think:

	depends on X86_LOCAL_APIC && !X86_VISWS

would be clearer and get the same.

Maciej

#26 lore raw

PATCH 1/1 x86: update mptable fix with no ioapic

In reply to Yinghai Lu

if the system doesn't have ioapic, we don't need to store entries for mptable update

arch/x86/kernel/acpi/boot.c +3 -0
index 04dbb35..e639d2f 100644
@@ -1173,6 +1173,9 @@ int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
 	if (!enable_update_mptable)
 		return 0;
 
+	if (!acpi_ioapic)
+		return 0;
+
 	/* print the entry should happen on mptable identically */
 	intsrc.mpc_type = MP_INTSRC;
 	intsrc.mpc_irqtype = mp_INT;
#27 lore raw

PATCH 1/1 x86: update mptable fix with no ioapic v2

if the system doesn't have ioapic, we don't need to store entries for mptable update

also let mp_config_acpi_gsi not call func in mpparse so later could decouple mpparse with acpi more easily

---
 arch/x86/kernel/acpi/boot.c |   87 ++++++++++++++++++++++++++++----------------
 arch/x86/kernel/mpparse.c   |   19 ++++-----
 include/asm-x86/mpspec.h    |    2 -
 3 files changed, 65 insertions(+), 43 deletions(-)
arch/x86/kernel/acpi/boot.c +56 -31
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
@@ -958,10 +958,37 @@ void __init mp_register_ioapic(int id, u
 	nr_ioapics++;
 }
 
+static void assign_to_mp_irq(struct mp_config_intsrc *m,
+				    struct mp_config_intsrc *mp_irq)
+{
+	memcpy(mp_irq, m, sizeof(struct mp_config_intsrc));
+}
+
+static int mp_irq_cmp(struct mp_config_intsrc *mp_irq,
+				struct mp_config_intsrc *m)
+{
+	return memcmp(mp_irq, m, sizeof(struct mp_config_intsrc));
+}
+
+static void save_mp_irq(struct mp_config_intsrc *m)
+{
+	int i;
+
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (!mp_irq_cmp(&mp_irqs[i], m))
+			return;
+	}
+
+	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
+	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+		panic("Max # of irq sources exceeded!!\n");
+}
+
 void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 {
 	int ioapic;
 	int pin;
+	struct mp_config_intsrc mp_irq;
 
 	/*
 	 * Convert 'gsi' to 'ioapic.pin'.
@@ -979,18 +1006,15 @@ void __init mp_override_legacy_irq(u8 bu
 	if ((bus_irq == 0) && (trigger == 3))
 		trigger = 1;
 
-	mp_irqs[mp_irq_entries].mp_type = MP_INTSRC;
-	mp_irqs[mp_irq_entries].mp_irqtype = mp_INT;
-	mp_irqs[mp_irq_entries].mp_irqflag = (trigger << 2) | polarity;
-	mp_irqs[mp_irq_entries].mp_srcbus = MP_ISA_BUS;
-	mp_irqs[mp_irq_entries].mp_srcbusirq = bus_irq;	/* IRQ */
-	mp_irqs[mp_irq_entries].mp_dstapic =
-			mp_ioapics[ioapic].mp_apicid;	/* APIC ID */
-	mp_irqs[mp_irq_entries].mp_dstirq = pin;	/* INTIN# */
-
-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
-		panic("Max # of irq sources exceeded!!\n");
+	mp_irq.mp_type = MP_INTSRC;
+	mp_irq.mp_irqtype = mp_INT;
+	mp_irq.mp_irqflag = (trigger << 2) | polarity;
+	mp_irq.mp_srcbus = MP_ISA_BUS;
+	mp_irq.mp_srcbusirq = bus_irq;	/* IRQ */
+	mp_irq.mp_dstapic = mp_ioapics[ioapic].mp_apicid; /* APIC ID */
+	mp_irq.mp_dstirq = pin;	/* INTIN# */
 
+	save_mp_irq(&mp_irq);
 }
 
 void __init mp_config_acpi_legacy_irqs(void)
@@ -998,6 +1022,7 @@ void __init mp_config_acpi_legacy_irqs(v
 	int i;
 	int ioapic;
 	unsigned int dstapic;
+	struct mp_config_intsrc mp_irq;
 
 #if defined (CONFIG_MCA) || defined (CONFIG_EISA)
 	/*
@@ -1050,16 +1075,15 @@ void __init mp_config_acpi_legacy_irqs(v
 			continue;	/* IRQ already used */
 		}
 
-		mp_irqs[mp_irq_entries].mp_type = MP_INTSRC;
-		mp_irqs[mp_irq_entries].mp_irqflag = 0;	/* Conforming */
-		mp_irqs[mp_irq_entries].mp_srcbus = MP_ISA_BUS;
-		mp_irqs[mp_irq_entries].mp_dstapic = dstapic;
-		mp_irqs[mp_irq_entries].mp_irqtype = mp_INT;
-		mp_irqs[mp_irq_entries].mp_srcbusirq = i; /* Identity mapped */
-		mp_irqs[mp_irq_entries].mp_dstirq = i;
+		mp_irq.mp_type = MP_INTSRC;
+		mp_irq.mp_irqflag = 0;	/* Conforming */
+		mp_irq.mp_srcbus = MP_ISA_BUS;
+		mp_irq.mp_dstapic = dstapic;
+		mp_irq.mp_irqtype = mp_INT;
+		mp_irq.mp_srcbusirq = i; /* Identity mapped */
+		mp_irq.mp_dstirq = i;
 
-		if (++mp_irq_entries == MAX_IRQ_SOURCES)
-			panic("Max # of irq sources exceeded!!\n");
+		save_mp_irq(&mp_irq);
 	}
 }
 
@@ -1167,25 +1191,26 @@ int mp_register_gsi(u32 gsi, int trigger
 int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
 			u32 gsi, int triggering, int polarity)
 {
-	struct mpc_config_intsrc intsrc;
+#ifdef CONFIG_X86_MPPARSE
+	struct mp_config_intsrc mp_irq;
 	int ioapic;
 
-	if (!enable_update_mptable)
+	if (!acpi_ioapic)
 		return 0;
 
 	/* print the entry should happen on mptable identically */
-	intsrc.mpc_type = MP_INTSRC;
-	intsrc.mpc_irqtype = mp_INT;
-	intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+	mp_irq.mp_type = MP_INTSRC;
+	mp_irq.mp_irqtype = mp_INT;
+	mp_irq.mp_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
 				(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
-	intsrc.mpc_srcbus = number;
-	intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+	mp_irq.mp_srcbus = number;
+	mp_irq.mp_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
 	ioapic = mp_find_ioapic(gsi);
-	intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
-	intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
-
-	MP_intsrc_info(&intsrc);
+	mp_irq.mp_dstapic = mp_ioapic_routing[ioapic].apic_id;
+	mp_irq.mp_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
 
+	save_mp_irq(&mp_irq);
+#endif
 	return 0;
 }
 
arch/x86/kernel/mpparse.c +9 -10
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
@@ -34,8 +34,6 @@
 #include <mach_mpparse.h>
 #endif
 
-int enable_update_mptable;
-
 /*
  * Checksum an MP configuration block.
  */
@@ -246,7 +244,7 @@ static void __init print_mp_irq_info(str
 		mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
 }
 
-static void assign_to_mp_irq(struct mpc_config_intsrc *m,
+static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
 				    struct mp_config_intsrc *mp_irq)
 {
 	mp_irq->mp_dstapic = m->mpc_dstapic;
@@ -270,7 +268,7 @@ static void __init assign_to_mpc_intsrc(
 	m->mpc_dstirq = mp_irq->mp_dstirq;
 }
 
-static int mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
 					struct mpc_config_intsrc *m)
 {
 	if (mp_irq->mp_dstapic != m->mpc_dstapic)
@@ -291,17 +289,16 @@ static int mp_irq_mpc_intsrc_cmp(struct 
 	return 0;
 }
 
-void MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
 {
 	int i;
 
 	print_MP_intsrc_info(m);
 
-	if (enable_update_mptable)
-		for (i = 0; i < mp_irq_entries; i++) {
-			if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
-				return;
-		}
+	for (i = 0; i < mp_irq_entries; i++) {
+		if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+			return;
+	}
 
 	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
 	if (++mp_irq_entries == MAX_IRQ_SOURCES)
@@ -1113,6 +1110,8 @@ out:
 	return 0;
 }
 
+static int __initdata enable_update_mptable;
+
 static int __init update_mptable_setup(char *str)
 {
 	enable_update_mptable = 1;
include/asm-x86/mpspec.h +0 -2
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
@@ -59,9 +59,7 @@ extern void mp_override_legacy_irq(u8 bu
 				   u32 gsi);
 extern void mp_config_acpi_legacy_irqs(void);
 extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
-extern void MP_intsrc_info(struct mpc_config_intsrc *m);
 #ifdef CONFIG_X86_IO_APIC
-extern int enable_update_mptable;
 extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
 				u32 gsi, int triggering, int polarity);
 #else
#28 lore raw

PATCH 1/1 x86: let MPS support selectable

---
 arch/x86/Kconfig            |   15 ++++++++++++++-
 arch/x86/Kconfig.debug      |    9 ---------
 arch/x86/mm/k8topology_64.c |    4 ++++
 3 files changed, 18 insertions(+), 10 deletions(-)
arch/x86/Kconfig +14 -1
Index: linux-2.6/arch/x86/Kconfig
===================================================================
@@ -233,6 +233,19 @@ config SMP
 
 	  If you don't know what to do here, say N.
 
+config X86_FIND_SMP_CONFIG
+	def_bool y
+	depends on X86_MPPARSE || X86_VOYAGER || X86_VISWS
+	depends on X86_32
+
+config X86_MPPARSE
+	def_bool y
+	bool "Enable MPS table"
+	depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
+	help
+	  For old smp systems that do not have proper acpi support. Newer systems
+	  (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
+
 choice
 	prompt "Subarchitecture Type"
 	default X86_PC
@@ -289,7 +302,7 @@ if X86_GENERICARCH
 
 config X86_NUMAQ
 	bool "NUMAQ (IBM/Sequent)"
-	depends on SMP && X86_32 && PCI
+	depends on SMP && X86_32 && PCI && X86_MPPARSE
 	select NUMA
 	help
 	  This option is used for getting Linux to run on a NUMAQ (IBM/Sequent)
arch/x86/Kconfig.debug +0 -9
Index: linux-2.6/arch/x86/Kconfig.debug
===================================================================
@@ -130,15 +130,6 @@ config 4KSTACKS
 	  on the VM subsystem for higher order allocations. This option
 	  will also use IRQ stacks to compensate for the reduced stackspace.
 
-config X86_FIND_SMP_CONFIG
-	def_bool y
-	depends on X86_MPPARSE || X86_VOYAGER || X86_VISWS
-	depends on X86_32
-
-config X86_MPPARSE
-	def_bool y
-	depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
-
 config DOUBLEFAULT
 	default y
 	bool "Enable doublefault exception handler" if EMBEDDED
arch/x86/mm/k8topology_64.c +4 -0
Index: linux-2.6/arch/x86/mm/k8topology_64.c
===================================================================
@@ -57,18 +57,22 @@ static __init void early_get_boot_cpu_id
 	/*
 	 * Find possible boot-time SMP configuration:
 	 */
+#ifdef CONFIG_X86_MPPARSE
 	early_find_smp_config();
+#endif
 #ifdef CONFIG_ACPI
 	/*
 	 * Read APIC information from ACPI tables.
 	 */
 	early_acpi_boot_init();
 #endif
+#ifdef CONFIG_X86_MPPARSE
 	/*
 	 * get boot-time SMP configuration:
 	 */
 	if (smp_found_config)
 		early_get_smp_config();
+#endif
 	early_init_lapic_mapping();
 }
 
Applied
#29 lore raw

Re: [PATCH] x86: let MPS support selectable

applied to tip/x86/mpparse, thanks.

Ingo

#30 lore raw

Re: [PATCH] x86: let MPS support selectable

Quoted 1 line · Ingo Molnar

applied to tip/x86/mpparse, thanks.

-tip testing found an early 64-bit bootup crash:

SMP: Allowing 0 CPUs, 0 hotplug CPUs
PANIC: early exception 0e rip 10:ffffffff804aeb32 error 2 cr2 ffff810040000000
Pid: 0, comm: swapper Not tainted 2.6.26-rc6 #8188

Call Trace:
 [<ffffffff80233f59>] ? printk+0x77/0x98
 [<ffffffff80d78196>] early_idt_handler+0x56/0x6a
 [<ffffffff804aeb32>] ? memset+0x32/0xc0
 [<ffffffff80d88026>] ? __alloc_bootmem_core+0x1ce/0x372
 [<ffffffff80d88343>] __alloc_bootmem_nopanic+0x35/0x60
 [<ffffffff80d8837f>] __alloc_bootmem+0x11/0x3a
 [<ffffffff80d7d329>] setup_per_cpu_areas+0x8d/0x249
 [<ffffffff80d78d61>] start_kernel+0x175/0x3a4
 [<ffffffff80d78365>] x86_64_start_kernel+0x165/0x16e

RIP 0x10

with this config (1GB RAM system):

http://redhat.com/~mingo/misc/config-Thu_Jun_19_14_22_37_CEST_2008.bad

so i reverted this patch for now.

Ingo

#31 lore raw

Re: [PATCH] x86: let MPS support selectable

In reply to Yinghai Lu
Quoted 10 lines · Yinghai Lu
arch/x86/Kconfig +6 -0
@@ -233,6 +233,19 @@ config SMP
 
 	  If you don't know what to do here, say N.
 
+config X86_FIND_SMP_CONFIG
+	def_bool y
+	depends on X86_MPPARSE || X86_VOYAGER || X86_VISWS
+	depends on X86_32
+
+config X86_MPPARSE

arch/x86/Kconfig config SMP · line 251

Quoted 10 lines
arch/x86/Kconfig +7 -0
+	def_bool y
+	bool "Enable MPS table"
+	depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
+	help
+	  For old smp systems that do not have proper acpi support. Newer systems
+	  (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
+
 choice
 	prompt "Subarchitecture Type"
 	default X86_PC

First of all you want to make sure at least one of ACPI and X86_MPPARSE
is enabled if X86_LOCAL_APIC or you risk a known-broken kernel configuration, e.g. SMP which has no slightest chance to work.

Personally I'd be happy to see CONFIG_ACPI_BOOT we used to have at one
point back just so that you can use ACPI tables to run an SMP system without the need to pull all the power management stuff. Useful if the MP table is broken beyond recovery. I am assuming it has been removed for a reason though.

Maciej

#32 lore raw

Re: [PATCH] x86: let MPS support selectable

Quoted 27 lines · Maciej W. Rozycki
Quoted 10 lines · Yinghai Lu
arch/x86/Kconfig +6 -0
@@ -233,6 +233,19 @@ config SMP
 
        If you don't know what to do here, say N.
 
+config X86_FIND_SMP_CONFIG
+     def_bool y
+     depends on X86_MPPARSE || X86_VOYAGER || X86_VISWS
+     depends on X86_32
+
+config X86_MPPARSE

arch/x86/Kconfig config SMP · line 251

Quoted 10 lines
arch/x86/Kconfig +7 -0
+     def_bool y
+     bool "Enable MPS table"
+     depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
+     help
+       For old smp systems that do not have proper acpi support. Newer systems
+       (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
+
 choice
      prompt "Subarchitecture Type"
      default X86_PC

First of all you want to make sure at least one of ACPI and X86_MPPARSE
is enabled if X86_LOCAL_APIC or you risk a known-broken kernel configuration, e.g. SMP which has no slightest chance to work.

Quoted 5 lines

Personally I'd be happy to see CONFIG_ACPI_BOOT we used to have at one
point back just so that you can use ACPI tables to run an SMP system without the need to pull all the power management stuff. Useful if the MP table is broken beyond recovery. I am assuming it has been removed for a reason though.

thanks. will try to add CONFIG_ACPI_BOOT...

YH

reviewer NAK
#33 lore raw

Re: [PATCH] x86: let MPS support selectable

Quoted 28 lines · Yinghai Lu
Quoted 27 lines · Maciej W. Rozycki
Quoted 10 lines · Yinghai Lu
arch/x86/Kconfig +6 -0
@@ -233,6 +233,19 @@ config SMP
 
        If you don't know what to do here, say N.
 
+config X86_FIND_SMP_CONFIG
+     def_bool y
+     depends on X86_MPPARSE || X86_VOYAGER || X86_VISWS
+     depends on X86_32
+
+config X86_MPPARSE

arch/x86/Kconfig config SMP · line 251

Quoted 10 lines
arch/x86/Kconfig +7 -0
+     def_bool y
+     bool "Enable MPS table"
+     depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
+     help
+       For old smp systems that do not have proper acpi support. Newer systems
+       (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
+
 choice
      prompt "Subarchitecture Type"
      default X86_PC

First of all you want to make sure at least one of ACPI and X86_MPPARSE
is enabled if X86_LOCAL_APIC or you risk a known-broken kernel configuration, e.g. SMP which has no slightest chance to work.

Quoted 7 lines
Quoted 5 lines

Personally I'd be happy to see CONFIG_ACPI_BOOT we used to have at one
point back just so that you can use ACPI tables to run an SMP system without the need to pull all the power management stuff. Useful if the MP table is broken beyond recovery. I am assuming it has been removed for a reason though.

thanks. will try to add CONFIG_ACPI_BOOT...

NAK.

CONFIG_ACPI_BOOT was removed because it was fundamentally ill-conceived and created a situation which was not only more difficult to maintain but also didn't work on most machines.
ACPI interrupt configuration depends on the ACPI interpreter, so to boot properly and configure interrupts with ACPI, you need 90% of the kernel's ACPI code present anyway.
The other 10% are the Linux policy drivers, fan, processor, etc, and those can be already be de-configured one by one if desired.

If you want to use ACPI just for enumerating processors, ie to see the HT that MPS usually doesn't include, you can boot with "acpi=ht", which will not enter ACPI mode or use ACPI for anything else. We used to have a compile option for this, but most people who used it did so by mistake and then complained that all sorts of things, (starting with the power button) didn't work, so it was removed.

I don't think we should be going out of our way to enhance MPS support. There probably isn't a single system shipped in this century that has MPS that doesen't have ACPI, while there are millions of systems that have ACPI and no MPS. MPS is going away, and making
it a config option prepares us for the day when we completely don't care about it any more.

However, I think that adding CONFIG_MPS before removing ACPI's depencency on mpparse.c has all risk and no value.

thanks,
-Len

#34 lore raw

Re: [PATCH] x86: let MPS support selectable

Quoted 6 lines · Len Brown

CONFIG_ACPI_BOOT was removed because it was fundamentally ill-conceived and created a situation which was not only more difficult to maintain but also didn't work on most machines.
ACPI interrupt configuration depends on the ACPI interpreter, so to boot properly and configure interrupts with ACPI, you need 90% of the kernel's ACPI code present anyway.

Fair enough.

Quoted 3 lines

If you want to use ACPI just for enumerating processors, ie to see the HT that MPS usually doesn't include, you can boot with "acpi=ht", which will not enter ACPI mode or use ACPI for anything else.

Hmm, that's quite obscure an option name! I would imagine most modern
systems used as servers would not want to do any power management, but would still prefer to use ACPI for enumeration of processors (including real ones!) and interrupts, because I gather it has become common if an MP table is included in a system at all, it is not exactly correct, because the responsible BIOS engineer simply had no clue to either fix it or discard entirely.

Quoted 4 lines

I don't think we should be going out of our way to enhance MPS support. There probably isn't a single system shipped in this century that has MPS that doesen't have ACPI, while there are millions of systems that have ACPI and no MPS. MPS is going away, and making

It looks like I have a fortunate exception, manufactured Dec 2007, which
has both in quite a good shape. :)

Quoted 2 lines

it a config option prepares us for the day when we completely don't care about it any more.

Well, this is why I think it is important to be able to drop unwanted
parts of the framework, such as the P from the ACPI acronym. If you say "acpi=ht" will do, that's great; otherwise relying on the MP table used to be the alternative.

I don't think we'll be able to drop MP table support entirely in the
foreseeable future though, like we haven't dropped support for the original 80386 yet. Old SMP systems with MP table support only are going to be around for a while -- I have a couple myself and I am sure they are still quite common.

Quoted 2 lines

However, I think that adding CONFIG_MPS before removing ACPI's depencency on mpparse.c has all risk and no value.

Agreed.

Maciej

#35 lore raw

Re: [PATCH] x86: let MPS support selectable

Quoted 4 lines · Maciej W. Rozycki
Quoted 2 lines

However, I think that adding CONFIG_MPS before removing ACPI's depencency on mpparse.c has all risk and no value.

Agreed.

that should be sorted out mostly in -tip/x86, Alexey Starikovskiy went through a marathon session decoupling them, about two months ago:

 $ git-shortlog --stat --author=astarikovskiy linus/master..tip/master

Alexey Starikovskiy (12):
x86: move es7000_plat out of mpparse.c
x86: complete move ACPI from mpparse.c
x86: make mp_ioapic_routing definition local
x86: make struct config_ioapic not MPspec specific
x86: make config_irqsrc not MPspec specific
x86: fix mpparse/acpi interaction
x86: Set pic_mode only if local apic code is present
x86: move pic_mode to apic_32.c
x86: move smp_found_config
x86: mp_bus_id_to_pci_bus is not needed
x86: move mp_bus_not_pci from mpparse.c
x86: allow MPPARSE to be deselected in SMP configs

22 files changed, 524 insertions(+), 501 deletions(-)

it's all in linux-next as well.

Ingo

A message that is not in the archive (sent off-list or not yet received): [email protected]

#37 lore raw

PATCH 1/1 x86: fix compiling when CONFIG_X86_MPPARSE is not set

---
 arch/x86/Kconfig            |    2 +-
 arch/x86/mm/k8topology_64.c |    4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)
arch/x86/Kconfig +1 -1
Index: linux-2.6/arch/x86/Kconfig
===================================================================
@@ -289,7 +289,7 @@ if X86_GENERICARCH
 
 config X86_NUMAQ
 	bool "NUMAQ (IBM/Sequent)"
-	depends on SMP && X86_32 && PCI
+	depends on SMP && X86_32 && PCI && X86_MPPARSE
 	select NUMA
 	help
 	  This option is used for getting Linux to run on a NUMAQ (IBM/Sequent)
arch/x86/mm/k8topology_64.c +4 -0
Index: linux-2.6/arch/x86/mm/k8topology_64.c
===================================================================
@@ -57,18 +57,22 @@ static __init void early_get_boot_cpu_id
 	/*
 	 * Find possible boot-time SMP configuration:
 	 */
+#ifdef CONFIG_X86_MPPARSE
 	early_find_smp_config();
+#endif
 #ifdef CONFIG_ACPI
 	/*
 	 * Read APIC information from ACPI tables.
 	 */
 	early_acpi_boot_init();
 #endif
+#ifdef CONFIG_X86_MPPARSE
 	/*
 	 * get boot-time SMP configuration:
 	 */
 	if (smp_found_config)
 		early_get_smp_config();
+#endif
 	early_init_lapic_mapping();
 }
 
#38 lore raw

PATCH 1/1 x86: check command line when CONFIG_X86_MPPARSE is not set

we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is not there

---
 arch/x86/kernel/acpi/boot.c |   12 ++++++++++++
 arch/x86/kernel/setup_32.c  |    2 ++
 arch/x86/kernel/setup_64.c  |    2 ++
 include/linux/acpi.h        |    5 +++++
 4 files changed, 21 insertions(+)
arch/x86/kernel/acpi/boot.c +12 -0
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
@@ -1740,6 +1740,18 @@ static int __init parse_pci(char *arg)
 }
 early_param("pci", parse_pci);
 
+void __init acpi_mps_check(void)
+{
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
+/* mptable code is not built-in*/
+	if (acpi_disabled || acpi_noirq) {
+		printk(KERN_ERR "MPS support code is not built-in\n",
+		       "so can not use acpi=off or acpi=noirq or pci=noacpi\n");
+		panic("MPS support is not built-in\n");
+	}
+#endif
+}
+
 #ifdef CONFIG_X86_IO_APIC
 static int __init parse_acpi_skip_timer_override(char *arg)
 {
arch/x86/kernel/setup_32.c +2 -0
Index: linux-2.6/arch/x86/kernel/setup_32.c
===================================================================
@@ -754,6 +754,8 @@ void __init setup_arch(char **cmdline_p)
 		early_dump_pci_devices();
 #endif
 
+	acpi_mps_check();
+
 	finish_e820_parsing();
 
 	probe_roms();
arch/x86/kernel/setup_64.c +2 -0
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -359,6 +359,8 @@ void __init setup_arch(char **cmdline_p)
 		early_dump_pci_devices();
 #endif
 
+	acpi_mps_check();
+
 #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
 	if (init_ohci1394_dma_early)
 		init_ohci1394_dma_on_all_controllers();
include/linux/acpi.h +5 -0
Index: linux-2.6/include/linux/acpi.h
===================================================================
@@ -82,6 +82,7 @@ char * __acpi_map_table (unsigned long p
 int early_acpi_boot_init(void);
 int acpi_boot_init (void);
 int acpi_boot_table_init (void);
+void acpi_mps_check (void);
 int acpi_numa_init (void);
 
 int acpi_table_init (void);
@@ -250,6 +251,10 @@ static inline int acpi_boot_table_init(v
 	return 0;
 }
 
+static inline void acpi_mps_check(void)
+{
+}
+
 static inline int acpi_check_resource_conflict(struct resource *res)
 {
 	return 0;
#39 lore raw

Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set

Quoted 2 lines · Yinghai Lu

we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is not there

hm, i think instead of a panic() we should print a warning and fall back to nosmp - an UP bootup should work just fine without any mptable information.

Ingo

#40 lore raw

Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set

Quoted 9 lines · Ingo Molnar
Quoted 2 lines · Yinghai Lu

we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is not there

hm, i think instead of a panic() we should print a warning and fall back to nosmp - an UP bootup should work just fine without any mptable information.

will look at it.

YH

#41 lore raw

Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set

In reply to Ingo Molnar
Quoted 3 lines · Ingo Molnar

hm, i think instead of a panic() we should print a warning and fall back to nosmp - an UP bootup should work just fine without any mptable information.

It sounds reasonable to me as well.

Maciej

#42 lore raw

PATCH 1/1 x86: check command line when CONFIG_X86_MPPARSE is not set v2

In reply to Yinghai Lu

if acpi=off, acpi=noirq and pci=noacpi, we need to disable apic

---
 arch/x86/kernel/acpi/boot.c |   14 ++++++++++++++
 arch/x86/kernel/apic_32.c   |    2 +-
 arch/x86/kernel/setup.c     |    4 ++++
 arch/x86/kernel/setup_32.c  |    5 +++++
 arch/x86/kernel/setup_64.c  |    9 +++++++++
 include/asm-x86/apic.h      |    6 +++++-
 include/linux/acpi.h        |    6 ++++++
 7 files changed, 44 insertions(+), 2 deletions(-)
arch/x86/kernel/acpi/boot.c +14 -0
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
@@ -1740,6 +1740,20 @@ static int __init parse_pci(char *arg)
 }
 early_param("pci", parse_pci);
 
+int __init acpi_mps_check(void)
+{
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
+/* mptable code is not built-in*/
+	if (acpi_disabled || acpi_noirq) {
+		printk(KERN_WARNING "MPS support code is not built-in.\n"
+		       "Using acpi=off or acpi=noirq or pci=noacpi "
+		       "may have problem\n");
+		return 1;
+	}
+#endif
+	return 0;
+}
+
 #ifdef CONFIG_X86_IO_APIC
 static int __init parse_acpi_skip_timer_override(char *arg)
 {
arch/x86/kernel/setup_32.c +5 -0
Index: linux-2.6/arch/x86/kernel/setup_32.c
===================================================================
@@ -689,6 +689,11 @@ void __init setup_arch(char **cmdline_p)
 		early_dump_pci_devices();
 #endif
 
+	if (acpi_mps_check()){
+		enable_local_apic = -1;
+		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+	}
+
 	finish_e820_parsing();
 
 	probe_roms();
arch/x86/kernel/setup_64.c +9 -0
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -319,6 +319,11 @@ void __init setup_arch(char **cmdline_p)
 		early_dump_pci_devices();
 #endif
 
+	if (acpi_mps_check()) {
+		disable_apic = 1;
+		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+	}
+
 #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
 	if (init_ohci1394_dma_early)
 		init_ohci1394_dma_on_all_controllers();
@@ -740,6 +745,10 @@ static void __cpuinit early_identify_cpu
 		cpu_devs[c->x86_vendor]->c_early_init(c);
 
 	validate_pat_support(c);
+
+	/* early_param could clear that, but recall get it set again */
+	if (disable_apic)
+		clear_cpu_cap(c, X86_FEATURE_APIC);
 }
 
 /*
include/linux/acpi.h +6 -0
Index: linux-2.6/include/linux/acpi.h
===================================================================
@@ -82,6 +82,7 @@ char * __acpi_map_table (unsigned long p
 int early_acpi_boot_init(void);
 int acpi_boot_init (void);
 int acpi_boot_table_init (void);
+int acpi_mps_check (void);
 int acpi_numa_init (void);
 
 int acpi_table_init (void);
@@ -250,6 +251,11 @@ static inline int acpi_boot_table_init(v
 	return 0;
 }
 
+static inline int acpi_mps_check(void)
+{
+	return 0;
+}
+
 static inline int acpi_check_resource_conflict(struct resource *res)
 {
 	return 0;
arch/x86/kernel/setup.c +4 -0
Index: linux-2.6/arch/x86/kernel/setup.c
===================================================================
@@ -161,6 +161,10 @@ void __init setup_per_cpu_areas(void)
 	char *ptr;
 	int cpu;
 
+	/* no processor from mptable or madt */
+	if (!num_processors)
+		num_processors = 1;
+
 #ifdef CONFIG_HOTPLUG_CPU
 	prefill_possible_map();
 #else
arch/x86/kernel/apic_32.c +1 -1
Index: linux-2.6/arch/x86/kernel/apic_32.c
===================================================================
@@ -57,7 +57,7 @@ unsigned long mp_lapic_addr;
  *
  * -1=force-disable, +1=force-enable
  */
-static int enable_local_apic __initdata;
+int enable_local_apic;
 
 /* Local APIC timer verification ok */
 static int local_apic_timer_verify_ok;
include/asm-x86/apic.h +5 -1
Index: linux-2.6/include/asm-x86/apic.h
===================================================================
@@ -39,8 +39,12 @@ extern int apic_verbosity;
 extern int local_apic_timer_c2_ok;
 
 extern int ioapic_force;
-extern int disable_apic;
 
+#ifdef CONFIG_X86_64
+extern int disable_apic;
+#else
+extern int enable_local_apic;
+#endif
 /*
  * Basic functions accessing APICs.
  */
#43 lore raw

PATCH 1/1 x86: clean up init_amd()

1. move out calling of check_enable_amd_mmconf_dmi out of setup_64.c put it into init_amd(), so don't need to make extra dmi check for system with other cpus.
2. 15 --> 0xf

---
 arch/x86/kernel/cpu/amd_64.c |   22 ++++++++++++++--------
 arch/x86/kernel/setup_64.c   |    4 ----
 2 files changed, 14 insertions(+), 12 deletions(-)
arch/x86/kernel/cpu/amd_64.c +14 -8
Index: linux-2.6/arch/x86/kernel/cpu/amd_64.c
===================================================================
@@ -131,7 +131,7 @@ static void __cpuinit init_amd(struct cp
 	 * Errata 63 for SH-B3 steppings
 	 * Errata 122 for all steppings (F+ have it disabled by default)
 	 */
-	if (c->x86 == 15) {
+	if (c->x86 == 0xf) {
 		rdmsrl(MSR_K8_HWCR, value);
 		value |= 1 << 6;
 		wrmsrl(MSR_K8_HWCR, value);
@@ -143,10 +143,11 @@ static void __cpuinit init_amd(struct cp
 	clear_cpu_cap(c, 0*32+31);
 
 	/* On C+ stepping K8 rep microcode works well for copy/memset */
-	level = cpuid_eax(1);
-	if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) ||
-			     level >= 0x0f58))
-		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+	if (c->x86 == 0xf) {
+		level = cpuid_eax(1);
+		if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
+			set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+	}
 	if (c->x86 == 0x10 || c->x86 == 0x11)
 		set_cpu_cap(c, X86_FEATURE_REP_GOOD);
 
@@ -157,7 +158,7 @@ static void __cpuinit init_amd(struct cp
 	level = get_model_name(c);
 	if (!level) {
 		switch (c->x86) {
-		case 15:
+		case 0xf:
 			/* Should distinguish Models here, but this is only
 			   a fallback anyways. */
 			strcpy(c->x86_model_id, "Hammer");
@@ -176,14 +177,19 @@ static void __cpuinit init_amd(struct cp
 	else
 		num_cache_leaves = 3;
 
-	if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11)
+	if (c->x86 >= 0xf && c->x86 <= 0x11)
 		set_cpu_cap(c, X86_FEATURE_K8);
 
 	/* MFENCE stops RDTSC speculation */
 	set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
 
-	if (c->x86 == 0x10)
+	if (c->x86 == 0x10) {
+		/* do this for boot cpu */
+		if (c == &boot_cpu_data)
+			check_enable_amd_mmconf_dmi();
+
 		fam10h_check_enable_mmcfg();
+	}
 
 	if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
 		unsigned long long tseg;
arch/x86/kernel/setup_64.c +0 -4
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
@@ -72,7 +72,6 @@
 #include <asm/topology.h>
 #include <asm/trampoline.h>
 #include <asm/pat.h>
-#include <asm/mmconfig.h>
 
 #include <mach_apic.h>
 #ifdef CONFIG_PARAVIRT
@@ -491,9 +490,6 @@ void __init setup_arch(char **cmdline_p)
 	conswitchp = &dummy_con;
 #endif
 #endif
-
-	/* do this before identify_cpu for boot cpu */
-	check_enable_amd_mmconf_dmi();
 }
 
 struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
#44 lore raw

Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set

In reply to Yinghai Lu

Hi!

Quoted 20 lines

we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is not there

---
 arch/x86/kernel/acpi/boot.c |   12 ++++++++++++
 arch/x86/kernel/setup_32.c  |    2 ++
 arch/x86/kernel/setup_64.c  |    2 ++
 include/linux/acpi.h        |    5 +++++
 4 files changed, 21 insertions(+)

Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================

arch/x86/kernel/acpi/boot.c +0 -0
@@ -1740,6 +1740,18 @@ static int __init parse_pci(char *arg)
 }
 early_param("pci", parse_pci);
 

arch/x86/kernel/acpi/boot.c static int __init parse_pci(char *arg) · line 1752

Quoted 10 lines
arch/x86/kernel/acpi/boot.c +10 -0
+void __init acpi_mps_check(void)
+{
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
+/* mptable code is not built-in*/
+	if (acpi_disabled || acpi_noirq) {
+		printk(KERN_ERR "MPS support code is not built-in\n",
+		       "so can not use acpi=off or acpi=noirq or pci=noacpi\n");
+		panic("MPS support is not built-in\n");
+	}
+#endif

I'd say this is good enough reason not to make X86_MPPARSE optional.

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#45 lore raw

Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set

Quoted 22 lines · Pavel Machek

Hi!

Quoted 20 lines

we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is not there

---
 arch/x86/kernel/acpi/boot.c |   12 ++++++++++++
 arch/x86/kernel/setup_32.c  |    2 ++
 arch/x86/kernel/setup_64.c  |    2 ++
 include/linux/acpi.h        |    5 +++++
 4 files changed, 21 insertions(+)

Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================

arch/x86/kernel/acpi/boot.c +0 -0
@@ -1740,6 +1740,18 @@ static int __init parse_pci(char *arg)
 }
 early_param("pci", parse_pci);
 
Quoted 13 lines

arch/x86/kernel/acpi/boot.c static int __init parse_pci(char *arg) · line 1752

Quoted 10 lines
arch/x86/kernel/acpi/boot.c +10 -0
+void __init acpi_mps_check(void)
+{
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
+/* mptable code is not built-in*/
+     if (acpi_disabled || acpi_noirq) {
+             printk(KERN_ERR "MPS support code is not built-in\n",
+                    "so can not use acpi=off or acpi=noirq or pci=noacpi\n");
+             panic("MPS support is not built-in\n");
+     }
+#endif

I'd say this is good enough reason not to make X86_MPPARSE optional.

new patch in tip/master, it will disable smp instead of panic.

YH

A message that is not in the archive (sent off-list or not yet received): [email protected]

Applied
#47 lore raw

Re: [PATCH] x86: simplify x86_mpparse dependency check

Quoted 4 lines · Yinghai Lu

[PATCH] x86: simplify x86_mpparse dependency check

"Maciej W. Rozycki" <[email protected]> said:

Quoted 8 lines
Quoted 6 lines

Given X86_64 selects X86_LOCAL_APIC I am not sure the redundancy seen above does not actually obscure the logic behind... I think:

      depends on X86_LOCAL_APIC && !X86_VISWS

would be clearer and get the same.

applied to tip/x86/mpparse - thanks Yinghai.

Ingo

reviewer
#50 lore raw

Re: [PATCH] x86: update mptable v7

In reply to Yinghai Lu
Quoted 5 lines · Yinghai Lu

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Doing so could confuse the heck out of the platform firmware, which will think that an ACPI-mode kernel is still running.

Note that it is a historic artifact, now considered a bug, that ACPI uses the MPS code. We should be divorcing these two bodies of code rather than mixing them further.

-Len

#51 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 5 lines · Len Brown
Quoted 1 line · Yinghai Lu
Quoted 7 lines
Quoted 4 lines

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Yes,

Quoted 7 lines

Doing so could confuse the heck out of the platform firmware, which will think that an ACPI-mode kernel is still running.

Note that it is a historic artifact, now considered a bug, that ACPI uses the MPS code. We should be divorcing these two bodies of code rather than mixing them further.

how about adding config option to not compile mptable related info?

YH

reviewer
#52 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 11 lines · Yinghai Lu
Quoted 10 lines · Len Brown
Quoted 5 lines · Yinghai Lu

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

Quoted 4 lines
Quoted 2 lines

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

Quoted 9 lines
Quoted 7 lines

Doing so could confuse the heck out of the platform firmware, which will think that an ACPI-mode kernel is still running.

Note that it is a historic artifact, now considered a bug, that ACPI uses the MPS code. We should be divorcing these two bodies of code rather than mixing them further.

how about adding config option to not compile mptable related info?

That's the idea.
CONFIG_MPS=n CONFIG_ACPI=y should build and run on every PC built in this century.

This was prototyped a long while back, but the tree has churned so much since then the old prototype is worthless.

-Len

#53 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 15 lines · Len Brown
Quoted 11 lines · Yinghai Lu
Quoted 10 lines · Len Brown
Quoted 5 lines · Yinghai Lu

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

other os still doesn't have update acpi irq routing support. but has broken mptable.

Quoted 11 lines
Quoted 10 lines
Quoted 8 lines

Doing so could confuse the heck out of the platform firmware, which will think that an ACPI-mode kernel is still running.

Note that it is a historic artifact, now considered a bug, that ACPI uses the MPS code. We should be divorcing these two bodies of code rather than mixing them further.

how about adding config option to not compile mptable related info?

Quoted 7 lines

That's the idea.
CONFIG_MPS=n CONFIG_ACPI=y should build and run on every PC built in this century.

This was prototyped a long while back, but the tree has churned so much since then the old prototype is worthless.

will look at it tonight.

when EFI is popular, there is no reason to compile mps related stuff in kernel again. esp for 64 bit.

BTW, it is funny that Suse still has fallsafe boot entry with acpi=off.

YH

#54 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 20 lines · Yinghai Lu
Quoted 7 lines · Len Brown
Quoted 3 lines · Yinghai Lu
Quoted 2 lines · Len Brown
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines · Yinghai Lu
Quoted 6 lines

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi

support

Quoted 4 lines
Quoted 4 lines
Quoted 3 lines

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

other os still doesn't have update acpi irq routing support. but has broken mptable.

Which is at least in part a reason to go back to the BIOS manufacturer and get them to fix their table.

I can see a warning coming from the kernel if these two tables are inconsistent though.

Quoted 13 lines
Quoted 13 lines
Quoted 8 lines
Quoted 6 lines

Doing so could confuse the heck out of the platform firmware, which will think that an ACPI-mode kernel is still running.

Note that it is a historic artifact, now considered a bug, that ACPI uses the MPS code. We should be divorcing these two bodies of code rather than mixing them further.

how about adding config option to not compile mptable related info?

That's the idea.
CONFIG_MPS=n CONFIG_ACPI=y should build and run on every PC built in this century.

Quoted 8 lines
Quoted 3 lines

This was prototyped a long while back, but the tree has churned so much since then the old prototype is worthless.

will look at it tonight.

when EFI is popular, there is no reason to compile mps related stuff in kernel again. esp for 64 bit.

? EFI has nothing to do with this. ACPI is popular today and EFI preserves EFI.

Quoted 1 line

BTW, it is funny that Suse still has fallsafe boot entry with acpi=off.

Silly question. Given that even writing to this table is platform specific. Any chance we can do this any a userspace utility writing through /dev/mem
for the systems that need it? We can even bundle the utility in the kexec-tools
package to make it easier to distribute.

Eric

#55 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 62 lines · Eric W. Biederman
Quoted 20 lines · Yinghai Lu
Quoted 7 lines · Len Brown
Quoted 3 lines · Yinghai Lu
Quoted 2 lines · Len Brown
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines · Yinghai Lu
Quoted 6 lines

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi

support

Quoted 4 lines
Quoted 4 lines
Quoted 3 lines

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

other os still doesn't have update acpi irq routing support. but has broken mptable.

Which is at least in part a reason to go back to the BIOS manufacturer and get them to fix their table.

I can see a warning coming from the kernel if these two tables are inconsistent though.

Quoted 13 lines
Quoted 13 lines
Quoted 8 lines
Quoted 6 lines

Doing so could confuse the heck out of the platform firmware, which will think that an ACPI-mode kernel is still running.

Note that it is a historic artifact, now considered a bug, that ACPI uses the MPS code. We should be divorcing these two bodies of code rather than mixing them further.

how about adding config option to not compile mptable related info?

That's the idea.
CONFIG_MPS=n CONFIG_ACPI=y should build and run on every PC built in this century.

Quoted 8 lines
Quoted 3 lines

This was prototyped a long while back, but the tree has churned so much since then the old prototype is worthless.

will look at it tonight.

when EFI is popular, there is no reason to compile mps related stuff in kernel again. esp for 64 bit.

? EFI has nothing to do with this. ACPI is popular today and EFI preserves EFI.

Quoted 6 lines
Quoted 1 line

BTW, it is funny that Suse still has fallsafe boot entry with acpi=off.

Silly question. Given that even writing to this table is platform specific. Any chance we can do this any a userspace utility writing through /dev/mem
for the systems that need it? We can even bundle the utility in the kexec-tools
package to make it easier to distribute.

interesting, never thought that.

need to call pci_acpi_enable_irq==>mp_config_acpi_gsi in kernel to save mp_irqs...

also we could use
old kernel kexec second kernel (with this patch and acpi, and uptable) and then use second kernel to kexec last kernel...

YH

#56 lore raw

Re: [PATCH] x86: update mptable v7

In reply to Eric W. Biederman
Quoted 6 lines · Eric W. Biederman

Silly question. Given that even writing to this table is platform specific. Any chance we can do this any a userspace utility writing through /dev/mem
for the systems that need it? We can even bundle the utility in the kexec-tools
package to make it easier to distribute.

I would prefer this to an in-kernel solution. I really feel this is too ugly to live.

-hpa

reviewer
#57 lore raw

Re: [PATCH] x86: update mptable v7

In reply to Eric W. Biederman
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
Quoted 6 lines
Quoted 4 lines

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

Quoted 5 lines
Quoted 2 lines

other os still doesn't have update acpi irq routing support. but has broken mptable.

Which is at least in part a reason to go back to the BIOS manufacturer and get them to fix their table.

Who says it is broken?

Quoted 2 lines

I can see a warning coming from the kernel if these two tables are inconsistent though.

Again, there may not *be* an MPS table, and if there is but the interrupt links are programmable, the MPS table may have very little in common with the state of the machine in ACPI mode.

I'm sorry, kexec continues to sound like science fiction to me. I don't understand why scribbling on upstream Linux in the name of science fiction makes any sense.

I just don't get it.

-Len

#58 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 9 lines · Len Brown
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

other os still doesn't have update acpi irq routing support. but has broken mptable.

Which is at least in part a reason to go back to the BIOS manufacturer and get them to fix their table.

Who says it is broken?

In the common case if not in general the MP table and the ACPI version of the same table, provide the same data in slight different formats.

Quoted 7 lines
Quoted 1 line

I can see a warning coming from the kernel if these two tables are

inconsistent

Quoted 1 line

though.

Again, there may not *be* an MPS table, and if there is but the interrupt links are programmable, the MPS table may have very little in common with the state of the machine in ACPI mode.

That I will believe.

Quoted 5 lines

I'm sorry, kexec continues to sound like science fiction to me. I don't understand why scribbling on upstream Linux in the name of science fiction makes any sense.

I just don't get it.

In the normal kexec case not the kexec on panic (aka kdump) we should have shutdown ACPI on the way down. So the machine won't be running in ACPI mode. I assume ACPI supports that.

What YH is doing does sound potentially dangerous. If you can indeed compare the two tables and in fact see they are inconsistent. That is a good case for printing a warning message. YH clearly started this because in his testing the MP table was broken and he had an older Enterprise kernel to run that had unusable ACPI support. That however is a BIOS bug. Pushing back on BIOS bugs and making them easy to find is always a good deal. Silently fixing them (not just working around them) seems unprecedented.

Eric

#59 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 43 lines · Eric W. Biederman
Quoted 9 lines · Len Brown
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

other os still doesn't have update acpi irq routing support. but has broken mptable.

Which is at least in part a reason to go back to the BIOS manufacturer and get them to fix their table.

Who says it is broken?

In the common case if not in general the MP table and the ACPI version of the same table, provide the same data in slight different formats.

Quoted 7 lines
Quoted 1 line

I can see a warning coming from the kernel if these two tables are

inconsistent

Quoted 1 line

though.

Again, there may not *be* an MPS table, and if there is but the interrupt links are programmable, the MPS table may have very little in common with the state of the machine in ACPI mode.

That I will believe.

Quoted 5 lines

I'm sorry, kexec continues to sound like science fiction to me. I don't understand why scribbling on upstream Linux in the name of science fiction makes any sense.

I just don't get it.

In the normal kexec case not the kexec on panic (aka kdump) we should have shutdown ACPI on the way down. So the machine won't be running in ACPI mode. I assume ACPI supports that.

Quoted 7 lines

What YH is doing does sound potentially dangerous. If you can indeed compare the two tables and in fact see they are inconsistent. That is a good case for printing a warning message. YH clearly started this because in his testing the MP table was broken and he had an older Enterprise kernel to run that had unusable ACPI support. That however is a BIOS bug. Pushing back on BIOS bugs and making them easy to find is always a good deal. Silently fixing them (not just working around them) seems unprecedented.

the patch did print out the old and updated mptable.

and that feature is enabled via "update_mptable" command line.

also it is useful for kexec from acpi kernel to no acpi kernel on MB with nvidia chipset with AMI BIOS.
becuase irq routing is different from mptable and acpi.

amd8111/amd8131 chipset with AMI bios has same irq routing from mptable and acpi.

Phonix BIOS, has one setup option APIC/PIC, and if select APIC, then irq routing from mptable and acpi is the same with
nvidia chipset.

YH

reviewer
#60 lore raw

Re: [PATCH] x86: update mptable v7

NAK on this entire direction.

Quoted 58 lines
Quoted 41 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

other os still doesn't have update acpi irq routing support. but has broken mptable.

Which is at least in part a reason to go back to the BIOS manufacturer and get them to fix their table.

Who says it is broken?

In the common case if not in general the MP table and the ACPI version of the same table, provide the same data in slight different formats.

Quoted 7 lines
Quoted 1 line

I can see a warning coming from the kernel if these two tables are

inconsistent

Quoted 1 line

though.

Again, there may not *be* an MPS table, and if there is but the interrupt links are programmable, the MPS table may have very little in common with the state of the machine in ACPI mode.

That I will believe.

Quoted 5 lines

I'm sorry, kexec continues to sound like science fiction to me. I don't understand why scribbling on upstream Linux in the name of science fiction makes any sense.

I just don't get it.

In the normal kexec case not the kexec on panic (aka kdump) we should have shutdown ACPI on the way down. So the machine won't be running in ACPI mode. I assume ACPI supports that.

Quoted 7 lines

What YH is doing does sound potentially dangerous. If you can indeed compare the two tables and in fact see they are inconsistent. That is a good case for printing a warning message. YH clearly started this because in his testing the MP table was broken and he had an older Enterprise kernel to run that had unusable ACPI support. That however is a BIOS bug. Pushing back on BIOS bugs and making them easy to find is always a good deal. Silently fixing them (not just working around them) seems unprecedented.

the patch did print out the old and updated mptable.

and that feature is enabled via "update_mptable" command line.

also it is useful for kexec from acpi kernel to no acpi kernel on MB with nvidia chipset with AMI BIOS.
becuase irq routing is different from mptable and acpi.

Quoted 6 lines

amd8111/amd8131 chipset with AMI bios has same irq routing from mptable and acpi.

Phonix BIOS, has one setup option APIC/PIC, and if select APIC, then irq routing from mptable and acpi is the same with
nvidia chipset.

So you know this can't NEVER be reliable, yet you continue to push for upstream changes that carry risk for all systems that DO work.

Please clue me into the use model that justifies risking a single line of Linux code for this effort.

-Len

#61 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 12 lines · Len Brown
Quoted 12 lines

the patch did print out the old and updated mptable.

and that feature is enabled via "update_mptable" command line.

also it is useful for kexec from acpi kernel to no acpi kernel on MB with nvidia chipset with AMI BIOS.
becuase irq routing is different from mptable and acpi.

amd8111/amd8131 chipset with AMI bios has same irq routing from mptable and acpi.

Quoted 6 lines
Quoted 3 lines

Phonix BIOS, has one setup option APIC/PIC, and if select APIC, then irq routing from mptable and acpi is the same with
nvidia chipset.

So you know this can't NEVER be reliable, yet you continue to push for upstream changes that carry risk for all systems that DO work.

Yinghai: Len has a point, could you please double-check that no potentially risky code runs by default anywhere, without a specific boot option? update_mptable is supposed to achieve that, but lets make sure it does its job.

I.e. the option should be like acpi=off - risky to do as it could break some systems, and it should not run by default. I have 3 systems myself where acpi=off results in a non-working system (hard hangs, non-detected devices, etc.).

Len: while i probably wont use the update_mptable option myself (i wont ever want to kexec into an OS with broken ACPI support), Yinghai's changes nevertheless have some use as they solve an external problem, and they also clean up a crufty area of code. Due to them we already found pre-existing bugs.

Ingo

#62 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 19 lines · Ingo Molnar
Quoted 16 lines · Len Brown
Quoted 15 lines

the patch did print out the old and updated mptable.

and that feature is enabled via "update_mptable" command line.

also it is useful for kexec from acpi kernel to no acpi kernel on MB with nvidia chipset with AMI BIOS.
becuase irq routing is different from mptable and acpi.

amd8111/amd8131 chipset with AMI bios has same irq routing from mptable and acpi.

Phonix BIOS, has one setup option APIC/PIC, and if select APIC, then irq routing from mptable and acpi is the same with
nvidia chipset.

Quoted 7 lines
Quoted 2 lines

So you know this can't NEVER be reliable, yet you continue to push for upstream changes that carry risk for all systems that DO work.

Yinghai: Len has a point, could you please double-check that no potentially risky code runs by default anywhere, without a specific boot option? update_mptable is supposed to achieve that, but lets make sure it does its job.

will double check that, and would consider to add CONFIG_UPDATE_MPTABLE to make it not be built in be default.

YH

#63 lore raw

Re: [PATCH] x86: update mptable v7

In reply to Ingo Molnar
Quoted 4 lines · Ingo Molnar

Yinghai: Len has a point, could you please double-check that no potentially risky code runs by default anywhere, without a specific boot option? update_mptable is supposed to achieve that, but lets make sure it does its job.

It's not done for the NUMAQ genericarch.

-Andi

reviewer
#64 lore raw

Re: [PATCH] x86: update mptable v7

In reply to Yinghai Lu
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 6 lines

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

other os still doesn't have update acpi irq routing support. but has broken mptable.

I don't see how this can work.

What if the the platform doesn't suport MPS -- the 2nd OS will try to run in PIC mode and will see only the legacy interrupts?

What if it does support MPS but ACPI has configured its PCI Interrupt Link Devices to direct interrupts to different IRQs that are described by MPS?

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Doing so could confuse the heck out of the platform firmware, which will think that an ACPI-mode kernel is still running.

There is state in the chip-set that the ACPI OS has set that makes no sense in an non-ACPI context and can lead to bizzare behaviour. The Links above is just one example.

the ACPI SCI interrupt is configured in ACPI mode only. What happens when the non-ACPI OS boots and GPE's fire and result in SCI's? They'll not get serviced and will kill that IRQ and anything else on it.

Can somebody clue me into why this concept
is something other than totally insane?

-Len

#65 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 16 lines · Len Brown
Quoted 16 lines
Quoted 15 lines
Quoted 11 lines
Quoted 9 lines
Quoted 6 lines

make mptable to be consistent to acpi routing, so we could
1. kexec kernel with acpi=off
2. workaround BIOS that acpi routing is working, but mptable is not right. so can use kernel/kexec to start other os that doesn't have good acpi support

Is this an effort to boot an ACPI-mode kernel,
and then kexec a non-ACPI kernel?

Yes,

Why is this feature needed?
There are a number of ways that the resulting kernel may fail, all platform specific.

Quoted 8 lines
Quoted 2 lines

other os still doesn't have update acpi irq routing support. but has broken mptable.

I don't see how this can work.

What if the the platform doesn't suport MPS -- the 2nd OS will try to run in PIC mode and will see only the legacy interrupts?

if the system doesn't support mps, this patch will bail out, because it can not find mptable

Quoted 4 lines

What if it does support MPS but ACPI has configured its PCI Interrupt Link Devices to direct interrupts to different IRQs that are described by MPS?

it will use irq from mptable that is updated according to acpi

when acpi irq set routing, and it will set some bits in pci config in southbridge, and the irq routing is consistent between HW and irq returned by acpi.
when first kernel is shutdown, it doesn't restore the bits about irq routing in pci config. So if keep updated mptable has correct pin, then device on second
kernel will work.

Quoted 4 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

Doing so could confuse the heck out of the platform firmware, which will think that an ACPI-mode kernel is still running.

Quoted 8 lines

There is state in the chip-set that the ACPI OS has set that makes no sense in an non-ACPI context and can lead to bizzare behaviour. The Links above is just one example.

the ACPI SCI interrupt is configured in ACPI mode only. What happens when the non-ACPI OS boots and GPE's fire and result in SCI's? They'll not get serviced and will kill that IRQ and anything else on it.

the patch doesn't change entries in mptable that pin < 16 and irq is not for pci device...

and normal sci/acpi is using 9..., and even mptable even doesn't has that entry. and there is no pci device share that irq with sci/acpi..., so it will be put into updated mptable.
so next kernel will mask that.

Quoted 3 lines

Can somebody clue me into why this concept
is something other than totally insane?

for system that have 6 pcie slots and more, with full populated cards. when boot with mptable, BIOS will use irq < 16 for all pci devices, and several devices will share same irq.
but when acpi is enabled, irqs are spanned all over.

also when pci card with several pci bridges is plugged in, the mptable is totally messed up, some slot will work, and some doesn't work.

YH

#66 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 10 lines · Yinghai Lu
Quoted 2 lines

Can somebody clue me into why this concept
is something other than totally insane?

for system that have 6 pcie slots and more, with full populated cards. when boot with mptable, BIOS will use irq < 16 for all pci devices, and several devices will share same irq.
but when acpi is enabled, irqs are spanned all over.

also when pci card with several pci bridges is plugged in, the mptable is totally messed up, some slot will work, and some doesn't work.

And the reason to worry about supporting non-ACPI on such hardware is what?

-hpa

#67 lore raw

Re: [PATCH] x86: update mptable v7

Quoted 10 lines · H. Peter Anvin
Quoted 9 lines · Yinghai Lu
Quoted 3 lines

Can somebody clue me into why this concept
is something other than totally insane?

for system that have 6 pcie slots and more, with full populated cards. when boot with mptable, BIOS will use irq < 16 for all pci devices, and several devices will share same irq.
but when acpi is enabled, irqs are spanned all over.

Quoted 4 lines
Quoted 2 lines

also when pci card with several pci bridges is plugged in, the mptable is totally messed up, some slot will work, and some doesn't work.

And the reason to worry about supporting non-ACPI on such hardware is what?

1. some other os doesn't support acpi well, and still use mptable.
2. show BIOS engineer how to fix mptable.

YH