x86: fixed mtrr change WP to WB
PATCH 1/1 x86: fixed mtrr change WP to WB
In reply to Yinghai Lu[PATCH] x86: fixed mtrr change WP to WB
so we modify mptable near below 1M
arch/x86/kernel/cpu/mtrr/generic.c +20 -0
@@ -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
@@ -794,6 +794,24 @@ x86_get_mtrr_mem_range(struct res_rangereturn 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(unsignedunsigned 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(unsignedif (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(unsignedprintk (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
@@ -83,6 +83,7 @@ void set_mtrr_prepare_save(struct set_mtvoid 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);
PATCH 1/1 x86: update mptable
In reply to a message not in the archivemake 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
@@ -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
H. Peter Anvin
reviewerQuoted 5 lines · Yinghai Lu
[PATCH] x86: fixed mtrr change WP to WB
so we modify mptable near below 1M
Signed-off-by Yinghai Lu <[email protected]>
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
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
Signed-off-by Yinghai Lu <[email protected]>
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
H. Peter Anvin
reviewerQuoted 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_physptrto 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
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_physptrto 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
H. Peter Anvin
reviewerQuoted 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
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
H. Peter Anvin
reviewerQuoted 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
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
PATCH 1/1 x86: update mptable v2
In reply to Yinghai Lumake 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
@@ -301,6 +301,35 @@ unsigned long __init find_e820_area_sizereturn -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
@@ -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
@@ -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
@@ -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
@@ -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)
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
@@ -243,6 +243,35 @@ unsigned long __init find_e820_area_sizereturn -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1152,6 +1152,28 @@ int mp_register_gsi(u32 gsi, int triggerreturn 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
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 supportcommand line:
update_mptablev2: add
alloc_mptablefor mptable that can not be changed.
new command line:alloc_mptable
v3: adjust for patch that move somemp_xxxto acpi..., andmpc_tomp_
-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
PATCH 1/1 x86: update mptable v4
In reply to Yinghai Lumake 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
@@ -243,6 +243,35 @@ unsigned long __init find_e820_area_sizereturn -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1151,6 +1151,28 @@ int mp_register_gsi(u32 gsi, int triggerreturn 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
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
@@ -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 mpmemcpy (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
@@ -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
@@ -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
@@ -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
@@ -1151,6 +1151,28 @@ int mp_register_gsi(u32 gsi, int triggerreturn 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
@@ -707,3 +707,31 @@ u64 __init find_e820_area_size(u64 startreturn -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
@@ -75,6 +75,7 @@ extern u64 find_e820_area_size(u64 startextern 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__ */
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
@@ -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 mpmemcpy (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
@@ -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
@@ -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
@@ -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
@@ -1164,6 +1164,28 @@ int mp_register_gsi(u32 gsi, int triggerreturn 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
@@ -739,3 +739,28 @@ u64 __init find_e820_area_size(u64 startreturn -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
@@ -84,6 +84,7 @@ extern u64 find_e820_area_size(u64 startextern 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__ */
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
@@ -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 mpmemcpy (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
@@ -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
@@ -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
@@ -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
@@ -1164,6 +1164,28 @@ int mp_register_gsi(u32 gsi, int triggerreturn 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
@@ -739,3 +739,28 @@ u64 __init find_e820_area_size(u64 startreturn -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
@@ -84,6 +84,7 @@ extern u64 find_e820_area_size(u64 startextern 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__ */
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
@@ -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)) {
Re: [PATCH] x86: update mptable v7 - fix
Quoted 11 lines · Yinghai Lu
[PATCH] x86: update mptable v7 - fix
need to call
early_reserve_e820to prelocate mptable for 32bitSigned-off-by Yinghai Lu <[email protected]>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
@@ -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
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_e820to prelocate mptable for 32bitSigned-off-by Yinghai Lu <[email protected]>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
--------------->
commit3c803fb3e1972566f7a1613f53f7e5a70fbde83fAuthor: Ingo Molnar <[email protected]> Date: Sun May 25 21:16:06 2008 +0200x86, 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'Signed-off-by Ingo Molnar <[email protected]>include/asm-x86/mpspec.h +0
-0@@ -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
-0extern 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
Re: [PATCH] x86: update mptable v7 - fix
Quoted 1 line · Yinghai Lu
thanks. So
X86_MPPARSEis 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
Re: [PATCH] x86: update mptable v7 - fix
In reply to Yinghai LuQuoted 1 line · Yinghai Lu
thanks. So
X86_MPPARSEis 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_6464-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
Re: [PATCH] x86: update mptable v7 - fix
Quoted 7 lines · Ingo Molnar
Quoted 1 line · Yinghai Lu
thanks. So
X86_MPPARSEis not needed when SMP is not enabled?here's the condition:
Quoted 7 lines
config
X86_MPPARSEdef_bool y depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_6464-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
H. Peter Anvin
reviewerRe: [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
Re: [PATCH] x86: update mptable v7 - fix
In reply to Ingo MolnarQuoted 9 lines · Ingo Molnar
here's the condition:
config
X86_MPPARSEdef_bool y depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_6464-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
PATCH 1/1 x86: update mptable fix with no ioapic
In reply to Yinghai Luif the system doesn't have ioapic, we don't need to store entries for mptable update
arch/x86/kernel/acpi/boot.c +3 -0
@@ -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;
Len Brown
reviewerRe: [PATCH] x86: update mptable v7
In reply to Yinghai LuQuoted 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
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 supportIs 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
PATCH 1/1 x86: update mptable fix with no ioapic v2
In reply to Yinghai Luif 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
@@ -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 buif ((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(vint 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(vcontinue ;/* 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 triggerint 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
@@ -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(structreturn 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
@@ -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
Len Brown
reviewerRe: [PATCH] x86: update mptable v7
In reply to Yinghai LuQuoted 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
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=nCONFIG_ACPI=yshould 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
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 acpisupport
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=nCONFIG_ACPI=yshould 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
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 acpisupport
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=nCONFIG_ACPI=yshould 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
Len Brown
reviewerRe: [PATCH] x86: update mptable v7
In reply to Yinghai LuQuoted 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 supportIs 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
H. Peter Anvin
reviewerRe: [PATCH] x86: update mptable v7
In reply to Eric W. BiedermanQuoted 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
Len Brown
reviewerRe: [PATCH] x86: update mptable v7
In reply to Eric W. BiedermanQuoted 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
Re: [PATCH] x86: update mptable v7
In reply to Len BrownQuoted 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 supportIs 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
H. Peter Anvin
reviewerRe: [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
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
Re: [PATCH] x86: update mptable v7
In reply to Len BrownQuoted 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
PATCH 1/1 x86: let MPS support selectable
In reply to Yinghai Lu--- 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
@@ -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
@@ -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
@@ -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 (); }
Re: [PATCH] x86: update mptable v7
In reply to Eric W. BiedermanQuoted 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
Ingo Molnar
AppliedRe: [PATCH] x86: update mptable fix with no ioapic v2
In reply to Yinghai LuQuoted 8 lines · Yinghai Lu
if the system doesn't have ioapic, we don't need to store entries for mptable update
also let
mp_config_acpi_gsinot call func in mpparse so later could decouple mpparse with acpi more easilyReported-by Daniel Exner <[email protected]>Signed-off-by Yinghai Lu <[email protected]>
applied to tip/x86/mpparse - thanks Yinghai.
Ingo
Ingo Molnar
AppliedRe: [PATCH] x86: let MPS support selectable
In reply to Yinghai Luapplied to tip/x86/mpparse, thanks.
Ingo
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
Re: [PATCH] x86: let MPS support selectable
In reply to Yinghai LuQuoted 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
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_MPPARSEarch/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_PCFirst of all you want to make sure at least one of ACPI and
X86_MPPARSE
is enabled ifX86_LOCAL_APICor 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_BOOTwe 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
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_MPPARSEarch/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_PCFirst of all you want to make sure at least one of ACPI and
X86_MPPARSE
is enabled ifX86_LOCAL_APICor 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_BOOTwe 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
Len Brown
reviewerRe: [PATCH] x86: update mptable v7
In reply to Yinghai LuNAK 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
Re: [PATCH] x86: let MPS support selectable
In reply to Len BrownQuoted 6 lines · Len Brown
CONFIG_ACPI_BOOTwas 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_MPSbefore removing ACPI's depencency onmpparse.chas all risk and no value.
Agreed.
Maciej
PATCH 1/1 x86: fix compiling when CONFIG_X86_MPPARSE is not set
In reply to a message not in the archive--- arch/x86/Kconfig | 2 +- arch/x86/mm/k8topology_64.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-)
arch/x86/Kconfig +1 -1
@@ -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
@@ -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 (); }
Re: [PATCH] x86: update mptable v7
In reply to Len BrownQuoted 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
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_mptableis 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
Re: [PATCH] x86: update mptable v7
In reply to Ingo MolnarQuoted 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_mptableis supposed to achieve that, but lets make sure it does its job.
It's not done for the NUMAQ genericarch.
-Andi
PATCH 1/1 x86: check command line when CONFIG_X86_MPPARSE is not set
In reply to Yinghai Luwe 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
@@ -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
@@ -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
@@ -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
@@ -82,6 +82,7 @@ char * __acpi_map_table (unsigned long pint 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(vreturn 0 ; } +static inline void acpi_mps_check (void ) +{ +} +static inline int acpi_check_resource_conflict (struct resource *res) {return 0 ;
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
Ingo Molnar
AppliedRe: [PATCH] x86: simplify x86_mpparse dependency check
In reply to a message not in the archiveQuoted 4 lines · Yinghai Lu
[PATCH] x86: simplify
x86_mpparsedependency check"Maciej W. Rozycki" <[email protected]> said:
Quoted 8 lines
Quoted 6 lines
Given
X86_64selectsX86_LOCAL_APICI am not sure the redundancy seen above does not actually obscure the logic behind... I think:depends on X86_LOCAL_APIC && !X86_VISWSwould be clearer and get the same.
Signed-off-by Yinghai Lu <[email protected]>
applied to tip/x86/mpparse - thanks Yinghai.
Ingo
Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
In reply to Ingo MolnarQuoted 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
Re: [PATCH] x86: simplify x86_mpparse dependency check
In reply to a message not in the archiveQuoted 1 line · Yinghai Lu
[PATCH] x86: simplify
x86_mpparsedependency check
Thanks for this clean-up.
Maciej
Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
In reply to Ingo MolnarQuoted 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
PATCH 1/1 x86: check command line when CONFIG_X86_MPPARSE is not set v2
In reply to Yinghai Luif 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
@@ -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
@@ -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
@@ -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
@@ -82,6 +82,7 @@ char * __acpi_map_table (unsigned long pint 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(vreturn 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
@@ -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
@@ -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
@@ -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. */
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
@@ -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 cpclear_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 cpelse 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
@@ -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 ] = {};
Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
In reply to Yinghai LuHi!
Quoted 20 lines
we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is not there
Signed-off-by Yinghai Lu <[email protected]>--- 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
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
Signed-off-by Yinghai Lu <[email protected]>--- 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_MPPARSEoptional.
new patch in tip/master, it will disable smp instead of panic.
YH
Re: [PATCH] x86: let MPS support selectable
In reply to Maciej W. RozyckiQuoted 4 lines · Maciej W. Rozycki
Quoted 2 lines
However, I think that adding
CONFIG_MPSbefore removing ACPI's depencency onmpparse.chas 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