* [PATCH] x86: update mptable
[not found] <200805041823.57198.yhlu.kernel@gmail.com>
@ 2008-05-06 17:38 ` Yinghai Lu
2008-05-06 17:41 ` [PATCH] x86: fixed mtrr change WP to WB Yinghai Lu
2008-05-07 7:48 ` [PATCH] x86: update mptable v2 Yinghai Lu
0 siblings, 2 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-05-06 17:38 UTC (permalink / raw)
To: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, H. Peter Anvin,
Andrew Morton
Cc: linux-kernel@vger.kernel.org
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
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_irq.c
+++ linux-2.6/drivers/acpi/pci_irq.c
@@ -474,6 +474,8 @@ acpi_pci_irq_derive(struct pci_dev *dev,
return irq;
}
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, u32 gsi, int triggering, int polarity);
+
/*
* acpi_pci_irq_enable
* success: return 0
@@ -570,6 +572,8 @@ int acpi_pci_irq_enable(struct pci_dev *
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq, triggering, polarity);
+
return 0;
}
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -180,14 +180,26 @@ 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)
{
- mp_irqs[mp_irq_entries] = *m;
printk(KERN_INFO "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);
+}
+
+static 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 (!memcmp(m, &mp_irqs[i], sizeof(*m)))
+ return;
+
+ mp_irqs[mp_irq_entries] = *m;
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
@@ -281,12 +293,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",
@@ -314,13 +323,28 @@ static int __init smp_read_mpc(struct mp
memcpy(str, mpc->mpc_productid, 12);
str[12] = 0;
-#ifdef CONFIG_X86_32
- mps_oem_check(mpc, oem, str);
-#endif
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+ char str[16];
+ char oem[10];
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+#ifdef CONFIG_X86_32
+ mps_oem_check(mpc, oem, str);
+#endif
+
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
@@ -1082,5 +1106,225 @@ int mp_register_gsi(u32 gsi, int trigger
return gsi;
}
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin, u32 gsi, int triggering, int polarity)
+{
+ struct mpc_config_intsrc intsrc;
+ int ioapic;
+
+ /* print the entry should happen on mptable identically */
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqtype = mp_INT;
+ intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ intsrc.mpc_srcbus = number;
+ intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+ intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+ MP_intsrc_info(&intsrc);
+
+ return 0;
+}
#endif /* CONFIG_X86_IO_APIC */
#endif /* CONFIG_ACPI */
+
+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].mpc_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mpc_irqflag != 0x0f)
+ continue;
+
+ if (mp_irqs[i].mpc_srcbus != m->mpc_srcbus)
+ continue;
+ if (mp_irqs[i].mpc_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];
+
+static int __init replace_intsrc_all(struct mp_config_table *mpc)
+{
+ int i;
+ int nr_m_spare = 0;
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ printk("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;
+
+ /* we can not fill blank, so just duplicate last one if needed */
+ printk("OLD ");
+ print_MP_intsrc_info(m);
+ i = get_MP_intsrc_index(m);
+ if (i > 0) {
+ memcpy(m, &mp_irqs[i], sizeof(*m));
+ printk("NEW ");
+ print_MP_intsrc_info(&mp_irqs[i]);
+ } else if (!i) {
+ /* legacy, do nothing */
+ } else if (nr_m_spare < SPARE_SLOT_NUM) {
+ /* -1, -2 */
+ /* not found, or duplicated ==> invalid entry, 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].mpc_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mpc_irqflag != 0x0f)
+ continue;
+
+ if (nr_m_spare > 0) {
+ printk("*NEW* found ");
+ nr_m_spare--;
+ memcpy(m_spare[nr_m_spare], &mp_irqs[i], sizeof(mp_irqs[i]));
+ m_spare[nr_m_spare] = NULL;
+ } else {
+ struct mpc_config_intsrc *m =
+ (struct mpc_config_intsrc *)mpt;
+ count += sizeof(struct mpc_config_intsrc);
+ mpc->mpc_length = count;
+ printk("No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+ memcpy(m, &mp_irqs[i], sizeof(mp_irqs[i]));
+ mpt += sizeof(struct mpc_config_intsrc);
+ }
+ print_MP_intsrc_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 int __init update_mp_table(void)
+{
+ char str[16];
+ char oem[10];
+ struct intel_mp_floating *mpf;
+
+ 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;
+
+ if (!smp_check_mpc(phys_to_virt(mpf->mpf_physptr), oem, str))
+ return 0;
+
+ printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+
+ /* only replace the one with mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
+ already in mp_irqs , stored by ... and mp_config_acpi_gsi ... need pci=routeirq */
+ replace_intsrc_all(phys_to_virt(mpf->mpf_physptr));
+
+ return 0;
+}
+
+late_initcall(update_mp_table);
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 17:38 ` [PATCH] x86: update mptable Yinghai Lu
@ 2008-05-06 17:41 ` Yinghai Lu
2008-05-06 17:48 ` H. Peter Anvin
2008-05-07 7:48 ` [PATCH] x86: update mptable v2 Yinghai Lu
1 sibling, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-05-06 17:41 UTC (permalink / raw)
To: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, H. Peter Anvin,
Andrew Morton
Cc: linux-kernel@vger.kernel.org
[PATCH] x86: fixed mtrr change WP to WB
so we modify mptable near below 1M
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/arch/x86/kernel/cpu/mtrr/generic.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/mtrr/generic.c
+++ linux-2.6/arch/x86/kernel/cpu/mtrr/generic.c
@@ -192,6 +192,26 @@ void mtrr_save_fixed_ranges(void *info)
get_fixed_ranges(mtrr_state.fixed_ranges);
}
+int update_mtrr_fixed_ranges(unsigned char old_type, unsigned char new_type)
+{
+ unsigned char *type;
+ int i;
+ int changed = 0;
+
+ if (!mtrr_state.have_fixed)
+ return 0;
+
+ type = mtrr_state.fixed_ranges;
+ for (i = 0; i < NUM_FIXED_RANGES; i++) {
+ if (type[i] == old_type) {
+ type[i] = new_type;
+ changed = 1;
+ }
+ }
+
+ return changed;
+}
+
static void print_fixed(unsigned base, unsigned step, const mtrr_type*types)
{
unsigned i;
Index: linux-2.6/arch/x86/kernel/cpu/mtrr/main.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/mtrr/main.c
+++ linux-2.6/arch/x86/kernel/cpu/mtrr/main.c
@@ -794,6 +794,24 @@ x86_get_mtrr_mem_range(struct res_range
return nr_range;
}
+extern int __initdata enable_update_mptable;
+
+static int __init fixed_mtrr_cleanup(void)
+{
+ unsigned char new_type;
+
+ if (!enable_update_mptable)
+ return 0;
+
+ /* AMD 0x1e, intel 0x06 */
+ new_type = 0x06;
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+ (boot_cpu_data.x86 >= 0x0f && boot_cpu_data.x86 <= 0x11))
+ new_type = 0x1e;
+
+ return update_mtrr_fixed_ranges(0x05, new_type);
+}
+
static struct res_range __initdata range[RANGE_NUM];
#ifdef CONFIG_MTRR_SANITIZER
@@ -1162,6 +1180,7 @@ static int __init mtrr_cleanup(unsigned
unsigned long range_sums, range_sums_new;
int index_good;
int num_reg_good;
+ int changed;
/* extra one for all 0 */
int num[MTRR_NUM_TYPES + 1];
@@ -1173,6 +1192,8 @@ static int __init mtrr_cleanup(unsigned
if (def != MTRR_TYPE_UNCACHABLE)
return 0;
+ changed = fixed_mtrr_cleanup();
+
/* get it and store it aside */
memset(range_state, 0, sizeof(range_state));
for (i = 0; i < num_var_ranges; i++) {
@@ -1196,12 +1217,12 @@ static int __init mtrr_cleanup(unsigned
/* check if we got UC entries */
if (!num[MTRR_TYPE_UNCACHABLE])
- return 0;
+ return changed;
/* check if we only had WB and UC */
if (num[MTRR_TYPE_WRBACK] + num[MTRR_TYPE_UNCACHABLE] !=
num_var_ranges - num[MTRR_NUM_TYPES])
- return 0;
+ return changed;
memset(range, 0, sizeof(range));
extra_remove_size = 0;
@@ -1363,12 +1384,12 @@ static int __init mtrr_cleanup(unsigned
printk(KERN_INFO "mtrr_cleanup: can not find optimal value\n");
printk(KERN_INFO "please specify mtrr_gran_size/mtrr_chunk_size\n");
- return 0;
+ return changed;
}
#else
static int __init mtrr_cleanup(unsigned address_bits)
{
- return 0;
+ return fixed_mtrr_cleanup();
}
#endif
Index: linux-2.6/arch/x86/kernel/cpu/mtrr/mtrr.h
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ linux-2.6/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -83,6 +83,7 @@ void set_mtrr_prepare_save(struct set_mt
void fill_mtrr_var_range(unsigned int index,
u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi);
+int update_mtrr_fixed_ranges(unsigned char old_type, unsigned char new_type);
void get_mtrr_state(void);
extern void set_mtrr_ops(struct mtrr_ops * ops);
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 17:41 ` [PATCH] x86: fixed mtrr change WP to WB Yinghai Lu
@ 2008-05-06 17:48 ` H. Peter Anvin
2008-05-06 18:24 ` Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: H. Peter Anvin @ 2008-05-06 17:48 UTC (permalink / raw)
To: yhlu.kernel
Cc: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, Andrew Morton,
linux-kernel@vger.kernel.org
Yinghai Lu wrote:
> [PATCH] x86: fixed mtrr change WP to WB
>
> so we modify mptable near below 1M
>
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 17:48 ` H. Peter Anvin
@ 2008-05-06 18:24 ` Yinghai Lu
2008-05-06 18:31 ` H. Peter Anvin
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-05-06 18:24 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, Andrew Morton,
linux-kernel@vger.kernel.org
On Tue, May 6, 2008 at 10:48 AM, H. Peter Anvin <hpa@zytor.com> wrote:
> Yinghai Lu wrote:
>
> > [PATCH] x86: fixed mtrr change WP to WB
> >
> > so we modify mptable near below 1M
> >
> > Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
> >
>
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 18:24 ` Yinghai Lu
@ 2008-05-06 18:31 ` H. Peter Anvin
2008-05-06 18:34 ` Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: H. Peter Anvin @ 2008-05-06 18:31 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, Andrew Morton,
linux-kernel@vger.kernel.org
Yinghai Lu wrote:
>>
>> 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?
>
Obviously, if you have already modified a table, you should save a
pointer to it, and not rely on the kernel scanning later.
-hpa
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 18:31 ` H. Peter Anvin
@ 2008-05-06 18:34 ` Yinghai Lu
2008-05-06 18:43 ` H. Peter Anvin
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-05-06 18:34 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, Andrew Morton,
linux-kernel@vger.kernel.org
On Tue, May 6, 2008 at 11:31 AM, H. Peter Anvin <hpa@zytor.com> wrote:
> Yinghai Lu wrote:
>
> >
> > >
> > > 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?
> >
> >
>
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 18:34 ` Yinghai Lu
@ 2008-05-06 18:43 ` H. Peter Anvin
2008-05-06 19:05 ` Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: H. Peter Anvin @ 2008-05-06 18:43 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, Andrew Morton,
linux-kernel@vger.kernel.org
Yinghai Lu wrote:
>
>> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 18:43 ` H. Peter Anvin
@ 2008-05-06 19:05 ` Yinghai Lu
2008-05-06 19:08 ` H. Peter Anvin
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-05-06 19:05 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, Andrew Morton,
linux-kernel@vger.kernel.org
On Tue, May 6, 2008 at 11:43 AM, H. Peter Anvin <hpa@zytor.com> wrote:
> Yinghai Lu wrote:
>
> >
> >
> > > 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.
but how about old stock kernel in RHEL3U9?
YH
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 19:05 ` Yinghai Lu
@ 2008-05-06 19:08 ` H. Peter Anvin
2008-05-06 19:15 ` Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: H. Peter Anvin @ 2008-05-06 19:08 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, Andrew Morton,
linux-kernel@vger.kernel.org
Yinghai Lu wrote:
>>>
>> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: fixed mtrr change WP to WB
2008-05-06 19:08 ` H. Peter Anvin
@ 2008-05-06 19:15 ` Yinghai Lu
0 siblings, 0 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-05-06 19:15 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, Andrew Morton,
linux-kernel@vger.kernel.org
On Tue, May 6, 2008 at 12:08 PM, H. Peter Anvin <hpa@zytor.com> wrote:
> Yinghai Lu wrote:
>
> >
> > >
> > > >
> > > >
> > > 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.
>
thanks. I will try to allocate 4k page for mpc and copy the old mpc to
it..., and reuse the old mpf.
YH
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable v2
2008-05-06 17:38 ` [PATCH] x86: update mptable Yinghai Lu
2008-05-06 17:41 ` [PATCH] x86: fixed mtrr change WP to WB Yinghai Lu
@ 2008-05-07 7:48 ` Yinghai Lu
2008-05-17 2:32 ` [PATCH] x86: update mptable v3 Yinghai Lu
1 sibling, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-05-07 7:48 UTC (permalink / raw)
To: Ingo Molnar, Eric W. Biederman, Thomas Gleixner, H. Peter Anvin,
Andrew Morton
Cc: linux-kernel@vger.kernel.org
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
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/arch/x86/kernel/e820_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/e820_64.c
+++ linux-2.6/arch/x86/kernel/e820_64.c
@@ -301,6 +301,35 @@ unsigned long __init find_e820_area_size
return -1UL;
}
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+unsigned long __init early_reserve_e820(unsigned long sizet,
+ unsigned long align)
+{
+ unsigned long start = 0, size = 0;
+ unsigned long addr;
+
+#ifdef CONFIG_X86_TRAMPOLINE
+ start = TRAMPOLINE_BASE;
+#endif
+ while (size < sizet)
+ start = find_e820_area_size(start, &size, align);
+
+ if (size < sizet)
+ return 0;
+
+ addr = start + size - sizet;
+
+ update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+
+ printk(KERN_INFO "update e820 for early_reserve_e820\n");
+ update_e820();
+
+ return addr;
+}
+
/*
* Find the highest page frame number we have available
*/
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -25,6 +25,7 @@
#include <asm/proto.h>
#include <asm/acpi.h>
#include <asm/bios_ebda.h>
+#include <asm/e820.h>
#include <mach_apic.h>
#ifdef CONFIG_X86_32
@@ -180,14 +181,26 @@ 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)
{
- mp_irqs[mp_irq_entries] = *m;
printk(KERN_INFO "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);
+}
+
+static 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 (!memcmp(m, &mp_irqs[i], sizeof(*m)))
+ return;
+
+ mp_irqs[mp_irq_entries] = *m;
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
@@ -281,12 +294,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",
@@ -314,13 +324,28 @@ static int __init smp_read_mpc(struct mp
memcpy(str, mpc->mpc_productid, 12);
str[12] = 0;
-#ifdef CONFIG_X86_32
- mps_oem_check(mpc, oem, str);
-#endif
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+ char str[16];
+ char oem[10];
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+#ifdef CONFIG_X86_32
+ mps_oem_check(mpc, oem, str);
+#endif
+
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
@@ -1082,5 +1107,316 @@ int mp_register_gsi(u32 gsi, int trigger
return gsi;
}
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity)
+{
+ struct mpc_config_intsrc intsrc;
+ int ioapic;
+
+ /* print the entry should happen on mptable identically */
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqtype = mp_INT;
+ intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ intsrc.mpc_srcbus = number;
+ intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+ intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+ MP_intsrc_info(&intsrc);
+
+ return 0;
+}
#endif /* CONFIG_X86_IO_APIC */
#endif /* CONFIG_ACPI */
+
+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].mpc_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mpc_irqflag != 0x0f)
+ continue;
+
+ if (mp_irqs[i].mpc_srcbus != m->mpc_srcbus)
+ continue;
+ if (mp_irqs[i].mpc_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];
+
+static int __init replace_intsrc_all(struct mp_config_table *mpc,
+ unsigned long mpc_new_phys,
+ unsigned long mpc_new_length)
+{
+ int i;
+ int nr_m_spare = 0;
+
+ 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_CONT "OLD ");
+ print_MP_intsrc_info(m);
+ i = get_MP_intsrc_index(m);
+ if (i > 0) {
+ memcpy(m, &mp_irqs[i], sizeof(*m));
+ printk(KERN_CONT "NEW ");
+ print_MP_intsrc_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].mpc_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mpc_irqflag != 0x0f)
+ continue;
+
+ if (nr_m_spare > 0) {
+ printk(KERN_INFO "*NEW* found ");
+ nr_m_spare--;
+ memcpy(m_spare[nr_m_spare], &mp_irqs[i],
+ sizeof(mp_irqs[i]));
+ 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;
+ }
+ }
+ memcpy(m, &mp_irqs[i], sizeof(mp_irqs[i]));
+ mpc->mpc_length = count;
+ mpt += sizeof(struct mpc_config_intsrc);
+ }
+ print_MP_intsrc_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);
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -56,6 +56,7 @@
#include <asm/desc.h>
#include <video/edid.h>
#include <asm/e820.h>
+#include <asm/mpspec.h>
#include <asm/dma.h>
#include <asm/gart.h>
#include <asm/mpspec.h>
@@ -372,6 +373,9 @@ void __init setup_arch(char **cmdline_p)
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
+
+ /* pre allocte 4k for mptable mpc */
+ early_reserve_e820_mpc_new();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(end_pfn)) {
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_irq.c
+++ linux-2.6/drivers/acpi/pci_irq.c
@@ -570,6 +570,9 @@ int acpi_pci_irq_enable(struct pci_dev *
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+ triggering, polarity);
+
return 0;
}
Index: linux-2.6/include/asm-x86/e820_64.h
===================================================================
--- linux-2.6.orig/include/asm-x86/e820_64.h
+++ linux-2.6/include/asm-x86/e820_64.h
@@ -50,6 +50,8 @@ extern void update_e820(void);
extern void reserve_early(unsigned long start, unsigned long end, char *name);
extern void free_early(unsigned long start, unsigned long end);
extern void early_res_to_bootmem(unsigned long start, unsigned long end);
+extern unsigned long early_reserve_e820(unsigned long sizet,
+ unsigned long align);
#endif/*!__ASSEMBLY__*/
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
--- linux-2.6.orig/include/asm-x86/mpspec.h
+++ linux-2.6/include/asm-x86/mpspec.h
@@ -41,6 +41,7 @@ extern unsigned long mp_lapic_addr;
extern void find_smp_config(void);
extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
void __cpuinit generic_processor_info(int apicid, int version);
#ifdef CONFIG_ACPI
@@ -49,6 +50,8 @@ extern void mp_override_legacy_irq(u8 bu
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity);
#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable v3
2008-05-07 7:48 ` [PATCH] x86: update mptable v2 Yinghai Lu
@ 2008-05-17 2:32 ` Yinghai Lu
2008-05-19 15:46 ` Ingo Molnar
2008-05-19 19:35 ` [PATCH] x86: update mptable v4 Yinghai Lu
0 siblings, 2 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-05-17 2:32 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
Cc: Eric W. Biederman, linux-kernel@vger.kernel.org
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_
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/arch/x86/kernel/e820_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/e820_64.c
+++ linux-2.6/arch/x86/kernel/e820_64.c
@@ -243,6 +243,35 @@ unsigned long __init find_e820_area_size
return -1UL;
}
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+unsigned long __init early_reserve_e820(unsigned long sizet,
+ unsigned long align)
+{
+ unsigned long start = 0, size = 0;
+ unsigned long addr;
+
+#ifdef CONFIG_X86_TRAMPOLINE
+ start = TRAMPOLINE_BASE;
+#endif
+ while (size < sizet)
+ start = find_e820_area_size(start, &size, align);
+
+ if (size < sizet)
+ return 0;
+
+ addr = start + size - sizet;
+
+ update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+
+ printk(KERN_INFO "update e820 for early_reserve_e820\n");
+ update_e820();
+
+ return addr;
+}
+
/*
* Find the highest page frame number we have available
*/
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -25,6 +25,7 @@
#include <asm/proto.h>
#include <asm/acpi.h>
#include <asm/bios_ebda.h>
+#include <asm/e820.h>
#include <mach_apic.h>
#ifdef CONFIG_X86_32
@@ -184,20 +185,82 @@ static void __init MP_ioapic_info(struct
nr_ioapics++;
}
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init print_MP_intsrc_info(struct mpc_config_intsrc *m)
{
- printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
- mp_irqs[mp_irq_entries].mp_dstapic = m->mpc_dstapic;
- mp_irqs[mp_irq_entries].mp_type = m->mpc_type;
- mp_irqs[mp_irq_entries].mp_irqtype = m->mpc_irqtype;
- mp_irqs[mp_irq_entries].mp_irqflag = m->mpc_irqflag;
- mp_irqs[mp_irq_entries].mp_srcbus = m->mpc_srcbus;
- mp_irqs[mp_irq_entries].mp_srcbusirq = m->mpc_srcbusirq;
- mp_irqs[mp_irq_entries].mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+{
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
+ " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+ (mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+ mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+}
+
+static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
+ struct mp_config_intsrc *mp_irq)
+{
+ mp_irq->mp_dstapic = m->mpc_dstapic;
+ mp_irq->mp_type = m->mpc_type;
+ mp_irq->mp_irqtype = m->mpc_irqtype;
+ mp_irq->mp_irqflag = m->mpc_irqflag;
+ mp_irq->mp_srcbus = m->mpc_srcbus;
+ mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+ mp_irq->mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ m->mpc_dstapic = mp_irq->mp_dstapic;
+ m->mpc_type = mp_irq->mp_type;
+ m->mpc_irqtype = mp_irq->mp_irqtype;
+ m->mpc_irqflag = mp_irq->mp_irqflag;
+ m->mpc_srcbus = mp_irq->mp_srcbus;
+ m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+ m->mpc_dstirq = mp_irq->mp_dstirq;
+}
+
+static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ if (mp_irq->mp_dstapic != m->mpc_dstapic)
+ return 1;
+ if (mp_irq->mp_type != m->mpc_type)
+ return 2;
+ if (mp_irq->mp_irqtype != m->mpc_irqtype)
+ return 3;
+ if (mp_irq->mp_irqflag != m->mpc_irqflag)
+ return 4;
+ if (mp_irq->mp_srcbus != m->mpc_srcbus)
+ return 5;
+ if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+ return 6;
+ if (mp_irq->mp_dstirq != m->mpc_dstirq)
+ return 7;
+
+ return 0;
+}
+
+void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+{
+ int i;
+
+ print_MP_intsrc_info(m);
+
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+ return;
+ }
+
+ assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
@@ -291,12 +354,9 @@ static inline void mps_oem_check(struct
* Read/parse the MPC
*/
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+ char *str)
{
- char str[16];
- char oem[10];
- int count = sizeof(*mpc);
- unsigned char *mpt = ((unsigned char *)mpc) + count;
if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
@@ -324,13 +384,28 @@ static int __init smp_read_mpc(struct mp
memcpy(str, mpc->mpc_productid, 12);
str[12] = 0;
-#ifdef CONFIG_X86_32
- mps_oem_check(mpc, oem, str);
-#endif
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+ char str[16];
+ char oem[10];
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+#ifdef CONFIG_X86_32
+ mps_oem_check(mpc, oem, str);
+#endif
+
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
@@ -798,3 +873,292 @@ void __init find_smp_config(void)
{
__find_smp_config(1);
}
+
+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];
+
+static int __init replace_intsrc_all(struct mp_config_table *mpc,
+ unsigned long mpc_new_phys,
+ unsigned long mpc_new_length)
+{
+ int i;
+ int nr_m_spare = 0;
+
+ 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);
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -56,6 +56,7 @@
#include <asm/desc.h>
#include <video/edid.h>
#include <asm/e820.h>
+#include <asm/mpspec.h>
#include <asm/dma.h>
#include <asm/gart.h>
#include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
+
+ /* pre allocte 4k for mptable mpc */
+ early_reserve_e820_mpc_new();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(end_pfn)) {
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_irq.c
+++ linux-2.6/drivers/acpi/pci_irq.c
@@ -570,6 +570,9 @@ int acpi_pci_irq_enable(struct pci_dev *
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+ triggering, polarity);
+
return 0;
}
Index: linux-2.6/include/asm-x86/e820_64.h
===================================================================
--- linux-2.6.orig/include/asm-x86/e820_64.h
+++ linux-2.6/include/asm-x86/e820_64.h
@@ -38,6 +38,8 @@ extern void finish_e820_parsing(void);
extern void reserve_early(unsigned long start, unsigned long end, char *name);
extern void free_early(unsigned long start, unsigned long end);
extern void early_res_to_bootmem(unsigned long start, unsigned long end);
+extern unsigned long early_reserve_e820(unsigned long sizet,
+ unsigned long align);
#endif/*!__ASSEMBLY__*/
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
--- linux-2.6.orig/include/asm-x86/mpspec.h
+++ linux-2.6/include/asm-x86/mpspec.h
@@ -41,6 +41,7 @@ extern unsigned long mp_lapic_addr;
extern void find_smp_config(void);
extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
void __cpuinit generic_processor_info(int apicid, int version);
#ifdef CONFIG_ACPI
@@ -49,6 +50,9 @@ extern void mp_override_legacy_irq(u8 bu
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity);
#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -1152,6 +1152,28 @@ int mp_register_gsi(u32 gsi, int trigger
return gsi;
}
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity)
+{
+ struct mpc_config_intsrc intsrc;
+ int ioapic;
+
+ /* print the entry should happen on mptable identically */
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqtype = mp_INT;
+ intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ intsrc.mpc_srcbus = number;
+ intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+ intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+ MP_intsrc_info(&intsrc);
+
+ return 0;
+}
+
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v3
2008-05-17 2:32 ` [PATCH] x86: update mptable v3 Yinghai Lu
@ 2008-05-19 15:46 ` Ingo Molnar
2008-05-19 19:35 ` [PATCH] x86: update mptable v4 Yinghai Lu
1 sibling, 0 replies; 65+ messages in thread
From: Ingo Molnar @ 2008-05-19 15:46 UTC (permalink / raw)
To: Yinghai Lu
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Eric W. Biederman,
linux-kernel@vger.kernel.org
* Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> make mptable to be consistent to acpi routing, so we could
> 1. kexec kernel with acpi=off
> 2. workaround BIOS that acpi routing is working, but mptable is not right.
> so can use kernel/kexec to start other os that doesn't have good acpi support
>
> command line: update_mptable
>
> v2: add alloc_mptable for mptable that can not be changed.
> new command line: alloc_mptable
> v3: adjust for patch that move some mp_xxx to acpi..., and mpc_ to mp_
-tip testing found a build failure with this patch:
arch/x86/kernel/mpparse.c: In function 'get_MP_intsrc_index':
arch/x86/kernel/mpparse.c:891: error: 'mp_irq_entries' undeclared (first use inthis function)
arch/x86/kernel/mpparse.c:891: error: (Each undeclared identifier is reported only once
[...]
config at:
http://redhat.com/~mingo/misc/config-Mon_May_19_17_38_13_CEST_2008.bad
Ingo
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable v4
2008-05-17 2:32 ` [PATCH] x86: update mptable v3 Yinghai Lu
2008-05-19 15:46 ` Ingo Molnar
@ 2008-05-19 19:35 ` Yinghai Lu
2008-05-19 19:52 ` [PATCH] x86: update mptable v5 Yinghai Lu
1 sibling, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-05-19 19:35 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman
Cc: linux-kernel@vger.kernel.org
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
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/arch/x86/kernel/e820_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/e820_64.c
+++ linux-2.6/arch/x86/kernel/e820_64.c
@@ -243,6 +243,35 @@ unsigned long __init find_e820_area_size
return -1UL;
}
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+unsigned long __init early_reserve_e820(unsigned long sizet,
+ unsigned long align)
+{
+ unsigned long start = 0, size = 0;
+ unsigned long addr;
+
+#ifdef CONFIG_X86_TRAMPOLINE
+ start = TRAMPOLINE_BASE;
+#endif
+ while (size < sizet)
+ start = find_e820_area_size(start, &size, align);
+
+ if (size < sizet)
+ return 0;
+
+ addr = start + size - sizet;
+
+ update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+
+ printk(KERN_INFO "update e820 for early_reserve_e820\n");
+ update_e820();
+
+ return addr;
+}
+
/*
* Find the highest page frame number we have available
*/
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -25,6 +25,7 @@
#include <asm/proto.h>
#include <asm/acpi.h>
#include <asm/bios_ebda.h>
+#include <asm/e820.h>
#include <mach_apic.h>
#ifdef CONFIG_X86_32
@@ -184,20 +185,82 @@ static void __init MP_ioapic_info(struct
nr_ioapics++;
}
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init print_MP_intsrc_info(struct mpc_config_intsrc *m)
{
- printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
- mp_irqs[mp_irq_entries].mp_dstapic = m->mpc_dstapic;
- mp_irqs[mp_irq_entries].mp_type = m->mpc_type;
- mp_irqs[mp_irq_entries].mp_irqtype = m->mpc_irqtype;
- mp_irqs[mp_irq_entries].mp_irqflag = m->mpc_irqflag;
- mp_irqs[mp_irq_entries].mp_srcbus = m->mpc_srcbus;
- mp_irqs[mp_irq_entries].mp_srcbusirq = m->mpc_srcbusirq;
- mp_irqs[mp_irq_entries].mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+{
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
+ " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+ (mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+ mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+}
+
+static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
+ struct mp_config_intsrc *mp_irq)
+{
+ mp_irq->mp_dstapic = m->mpc_dstapic;
+ mp_irq->mp_type = m->mpc_type;
+ mp_irq->mp_irqtype = m->mpc_irqtype;
+ mp_irq->mp_irqflag = m->mpc_irqflag;
+ mp_irq->mp_srcbus = m->mpc_srcbus;
+ mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+ mp_irq->mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ m->mpc_dstapic = mp_irq->mp_dstapic;
+ m->mpc_type = mp_irq->mp_type;
+ m->mpc_irqtype = mp_irq->mp_irqtype;
+ m->mpc_irqflag = mp_irq->mp_irqflag;
+ m->mpc_srcbus = mp_irq->mp_srcbus;
+ m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+ m->mpc_dstirq = mp_irq->mp_dstirq;
+}
+
+static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ if (mp_irq->mp_dstapic != m->mpc_dstapic)
+ return 1;
+ if (mp_irq->mp_type != m->mpc_type)
+ return 2;
+ if (mp_irq->mp_irqtype != m->mpc_irqtype)
+ return 3;
+ if (mp_irq->mp_irqflag != m->mpc_irqflag)
+ return 4;
+ if (mp_irq->mp_srcbus != m->mpc_srcbus)
+ return 5;
+ if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+ return 6;
+ if (mp_irq->mp_dstirq != m->mpc_dstirq)
+ return 7;
+
+ return 0;
+}
+
+void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+{
+ int i;
+
+ print_MP_intsrc_info(m);
+
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+ return;
+ }
+
+ assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
@@ -291,12 +354,9 @@ static inline void mps_oem_check(struct
* Read/parse the MPC
*/
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+ char *str)
{
- char str[16];
- char oem[10];
- int count = sizeof(*mpc);
- unsigned char *mpt = ((unsigned char *)mpc) + count;
if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
@@ -324,13 +384,28 @@ static int __init smp_read_mpc(struct mp
memcpy(str, mpc->mpc_productid, 12);
str[12] = 0;
-#ifdef CONFIG_X86_32
- mps_oem_check(mpc, oem, str);
-#endif
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+ char str[16];
+ char oem[10];
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+#ifdef CONFIG_X86_32
+ mps_oem_check(mpc, oem, str);
+#endif
+
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
@@ -798,3 +873,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;
+
+#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);
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -56,6 +56,7 @@
#include <asm/desc.h>
#include <video/edid.h>
#include <asm/e820.h>
+#include <asm/mpspec.h>
#include <asm/dma.h>
#include <asm/gart.h>
#include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
+
+ /* pre allocte 4k for mptable mpc */
+ early_reserve_e820_mpc_new();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(end_pfn)) {
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_irq.c
+++ linux-2.6/drivers/acpi/pci_irq.c
@@ -570,6 +570,9 @@ int acpi_pci_irq_enable(struct pci_dev *
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+ triggering, polarity);
+
return 0;
}
Index: linux-2.6/include/asm-x86/e820_64.h
===================================================================
--- linux-2.6.orig/include/asm-x86/e820_64.h
+++ linux-2.6/include/asm-x86/e820_64.h
@@ -38,6 +38,8 @@ extern void finish_e820_parsing(void);
extern void reserve_early(unsigned long start, unsigned long end, char *name);
extern void free_early(unsigned long start, unsigned long end);
extern void early_res_to_bootmem(unsigned long start, unsigned long end);
+extern unsigned long early_reserve_e820(unsigned long sizet,
+ unsigned long align);
#endif/*!__ASSEMBLY__*/
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
--- linux-2.6.orig/include/asm-x86/mpspec.h
+++ linux-2.6/include/asm-x86/mpspec.h
@@ -41,6 +41,7 @@ extern unsigned long mp_lapic_addr;
extern void find_smp_config(void);
extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
void __cpuinit generic_processor_info(int apicid, int version);
#ifdef CONFIG_ACPI
@@ -49,6 +50,9 @@ extern void mp_override_legacy_irq(u8 bu
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity);
#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -1151,6 +1151,28 @@ int mp_register_gsi(u32 gsi, int trigger
return gsi;
}
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity)
+{
+ struct mpc_config_intsrc intsrc;
+ int ioapic;
+
+ /* print the entry should happen on mptable identically */
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqtype = mp_INT;
+ intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ intsrc.mpc_srcbus = number;
+ intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+ intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+ MP_intsrc_info(&intsrc);
+
+ return 0;
+}
+
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable v5
2008-05-19 19:35 ` [PATCH] x86: update mptable v4 Yinghai Lu
@ 2008-05-19 19:52 ` Yinghai Lu
2008-05-25 23:00 ` [PATCH] x86: update mptable v6 Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-05-19 19:52 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Eric W. Biederman,
linux-kernel@vger.kernel.org
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
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -25,6 +25,7 @@
#include <asm/proto.h>
#include <asm/acpi.h>
#include <asm/bios_ebda.h>
+#include <asm/e820.h>
#include <mach_apic.h>
#ifdef CONFIG_X86_32
@@ -184,20 +185,82 @@ static void __init MP_ioapic_info(struct
nr_ioapics++;
}
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init print_MP_intsrc_info(struct mpc_config_intsrc *m)
{
- printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
- mp_irqs[mp_irq_entries].mp_dstapic = m->mpc_dstapic;
- mp_irqs[mp_irq_entries].mp_type = m->mpc_type;
- mp_irqs[mp_irq_entries].mp_irqtype = m->mpc_irqtype;
- mp_irqs[mp_irq_entries].mp_irqflag = m->mpc_irqflag;
- mp_irqs[mp_irq_entries].mp_srcbus = m->mpc_srcbus;
- mp_irqs[mp_irq_entries].mp_srcbusirq = m->mpc_srcbusirq;
- mp_irqs[mp_irq_entries].mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+{
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
+ " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+ (mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+ mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+}
+
+static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
+ struct mp_config_intsrc *mp_irq)
+{
+ mp_irq->mp_dstapic = m->mpc_dstapic;
+ mp_irq->mp_type = m->mpc_type;
+ mp_irq->mp_irqtype = m->mpc_irqtype;
+ mp_irq->mp_irqflag = m->mpc_irqflag;
+ mp_irq->mp_srcbus = m->mpc_srcbus;
+ mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+ mp_irq->mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ m->mpc_dstapic = mp_irq->mp_dstapic;
+ m->mpc_type = mp_irq->mp_type;
+ m->mpc_irqtype = mp_irq->mp_irqtype;
+ m->mpc_irqflag = mp_irq->mp_irqflag;
+ m->mpc_srcbus = mp_irq->mp_srcbus;
+ m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+ m->mpc_dstirq = mp_irq->mp_dstirq;
+}
+
+static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ if (mp_irq->mp_dstapic != m->mpc_dstapic)
+ return 1;
+ if (mp_irq->mp_type != m->mpc_type)
+ return 2;
+ if (mp_irq->mp_irqtype != m->mpc_irqtype)
+ return 3;
+ if (mp_irq->mp_irqflag != m->mpc_irqflag)
+ return 4;
+ if (mp_irq->mp_srcbus != m->mpc_srcbus)
+ return 5;
+ if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+ return 6;
+ if (mp_irq->mp_dstirq != m->mpc_dstirq)
+ return 7;
+
+ return 0;
+}
+
+void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+{
+ int i;
+
+ print_MP_intsrc_info(m);
+
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+ return;
+ }
+
+ assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
@@ -291,12 +354,9 @@ static inline void mps_oem_check(struct
* Read/parse the MPC
*/
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+ char *str)
{
- char str[16];
- char oem[10];
- int count = sizeof(*mpc);
- unsigned char *mpt = ((unsigned char *)mpc) + count;
if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
@@ -324,13 +384,28 @@ static int __init smp_read_mpc(struct mp
memcpy(str, mpc->mpc_productid, 12);
str[12] = 0;
-#ifdef CONFIG_X86_32
- mps_oem_check(mpc, oem, str);
-#endif
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+ char str[16];
+ char oem[10];
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+#ifdef CONFIG_X86_32
+ mps_oem_check(mpc, oem, str);
+#endif
+
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
@@ -798,3 +873,296 @@ void __init find_smp_config(void)
{
__find_smp_config(1);
}
+
+#ifdef CONFIG_X86_IO_APIC
+static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+
+static int __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
+{
+ int i;
+
+ if (m->mpc_irqtype != mp_INT)
+ return 0;
+
+ if (m->mpc_irqflag != 0x0f)
+ return 0;
+
+ /* not legacy */
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (mp_irqs[i].mp_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mp_irqflag != 0x0f)
+ continue;
+
+ if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
+ continue;
+ if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
+ continue;
+ if (irq_used[i]) {
+ /* already claimed */
+ return -2;
+ }
+ irq_used[i] = 1;
+ return i;
+ }
+
+ /* not found */
+ return -1;
+}
+
+#define SPARE_SLOT_NUM 20
+
+static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+#endif
+
+static int __init replace_intsrc_all(struct mp_config_table *mpc,
+ unsigned long mpc_new_phys,
+ unsigned long mpc_new_length)
+{
+#ifdef CONFIG_X86_IO_APIC
+ int i;
+ int nr_m_spare = 0;
+#endif
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
+ while (count < mpc->mpc_length) {
+ switch (*mpt) {
+ case MP_PROCESSOR:
+ {
+ struct mpc_config_processor *m =
+ (struct mpc_config_processor *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ case MP_BUS:
+ {
+ struct mpc_config_bus *m =
+ (struct mpc_config_bus *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ case MP_IOAPIC:
+ {
+ mpt += sizeof(struct mpc_config_ioapic);
+ count += sizeof(struct mpc_config_ioapic);
+ break;
+ }
+ case MP_INTSRC:
+ {
+#ifdef CONFIG_X86_IO_APIC
+ struct mpc_config_intsrc *m =
+ (struct mpc_config_intsrc *)mpt;
+
+ printk(KERN_INFO "OLD ");
+ print_MP_intsrc_info(m);
+ i = get_MP_intsrc_index(m);
+ if (i > 0) {
+ assign_to_mpc_intsrc(&mp_irqs[i], m);
+ printk(KERN_INFO "NEW ");
+ print_mp_irq_info(&mp_irqs[i]);
+ } else if (!i) {
+ /* legacy, do nothing */
+ } else if (nr_m_spare < SPARE_SLOT_NUM) {
+ /*
+ * not found (-1), or duplicated (-2)
+ * are invalid entries,
+ * we need to use the slot later
+ */
+ m_spare[nr_m_spare] = m;
+ nr_m_spare++;
+ }
+#endif
+ mpt += sizeof(struct mpc_config_intsrc);
+ count += sizeof(struct mpc_config_intsrc);
+ break;
+ }
+ case MP_LINTSRC:
+ {
+ struct mpc_config_lintsrc *m =
+ (struct mpc_config_lintsrc *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ default:
+ /* wrong mptable */
+ printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+ printk(KERN_ERR "type %x\n", *mpt);
+ print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
+ 1, mpc, mpc->mpc_length, 1);
+ goto out;
+ }
+ }
+
+#ifdef CONFIG_X86_IO_APIC
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (irq_used[i])
+ continue;
+
+ if (mp_irqs[i].mp_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mp_irqflag != 0x0f)
+ continue;
+
+ if (nr_m_spare > 0) {
+ printk(KERN_INFO "*NEW* found ");
+ nr_m_spare--;
+ assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+ m_spare[nr_m_spare] = NULL;
+ } else {
+ struct mpc_config_intsrc *m =
+ (struct mpc_config_intsrc *)mpt;
+ count += sizeof(struct mpc_config_intsrc);
+ if (!mpc_new_phys) {
+ printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+ } else {
+ if (count <= mpc_new_length)
+ printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
+ else {
+ printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
+ goto out;
+ }
+ }
+ assign_to_mpc_intsrc(&mp_irqs[i], m);
+ mpc->mpc_length = count;
+ mpt += sizeof(struct mpc_config_intsrc);
+ }
+ print_mp_irq_info(&mp_irqs[i]);
+ }
+#endif
+out:
+ /* update checksum */
+ mpc->mpc_checksum = 0;
+ mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
+ mpc->mpc_length);
+
+ return 0;
+}
+
+int __initdata enable_update_mptable;
+
+static int __init update_mptable_setup(char *str)
+{
+ enable_update_mptable = 1;
+ return 0;
+}
+early_param("update_mptable", update_mptable_setup);
+
+static unsigned long __initdata mpc_new_phys;
+static unsigned long mpc_new_length __initdata = 4096;
+
+#ifdef CONFIG_X86_64
+/* alloc_mptable or alloc_mptable=4k */
+static int __initdata alloc_mptable;
+static int __init parse_alloc_mptable_opt(char *p)
+{
+ enable_update_mptable = 1;
+ alloc_mptable = 1;
+ if (!p)
+ return 0;
+ mpc_new_length = memparse(p, &p);
+ return 0;
+}
+early_param("alloc_mptable", parse_alloc_mptable_opt);
+
+void __init early_reserve_e820_mpc_new(void)
+{
+ if (enable_update_mptable && alloc_mptable)
+ mpc_new_phys = early_reserve_e820(mpc_new_length, 4);
+}
+#else
+void __init early_reserve_e820_mpc_new(void)
+{
+}
+#endif
+
+static int __init update_mp_table(void)
+{
+ char str[16];
+ char oem[10];
+ struct intel_mp_floating *mpf;
+ struct mp_config_table *mpc;
+ struct mp_config_table *mpc_new;
+
+ if (!enable_update_mptable)
+ return 0;
+
+ mpf = mpf_found;
+ if (!mpf)
+ return 0;
+
+ /*
+ * Now see if we need to go further.
+ */
+ if (mpf->mpf_feature1 != 0)
+ return 0;
+
+ if (!mpf->mpf_physptr)
+ return 0;
+
+ mpc = phys_to_virt(mpf->mpf_physptr);
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+ printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf));
+ printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+
+ if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
+ mpc_new_phys = 0;
+ printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
+ mpc_new_length);
+ }
+
+ if (!mpc_new_phys) {
+ unsigned char old, new;
+ /* check if we can change the postion */
+ mpc->mpc_checksum = 0;
+ old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+ mpc->mpc_checksum = 0xff;
+ new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+ if (old == new) {
+ printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+ return 0;
+ }
+ printk(KERN_INFO "use in-positon replacing\n");
+ } else {
+ mpf->mpf_physptr = mpc_new_phys;
+ mpc_new = phys_to_virt(mpc_new_phys);
+ memcpy(mpc_new, mpc, mpc->mpc_length);
+ mpc = mpc_new;
+ /* check if we can modify that */
+ if (mpc_new_phys - mpf->mpf_physptr) {
+ struct intel_mp_floating *mpf_new;
+ /* steal 16 bytes from [0, 1k) */
+ printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+ mpf_new = phys_to_virt(0x400 - 16);
+ memcpy(mpf_new, mpf, 16);
+ mpf = mpf_new;
+ mpf->mpf_physptr = mpc_new_phys;
+ }
+ mpf->mpf_checksum = 0;
+ mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16);
+ printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr);
+ }
+
+ /*
+ * only replace the one with mp_INT and
+ * MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
+ * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
+ * may need pci=routeirq for all coverage
+ */
+ replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);
+
+ return 0;
+}
+
+late_initcall(update_mp_table);
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -56,6 +56,7 @@
#include <asm/desc.h>
#include <video/edid.h>
#include <asm/e820.h>
+#include <asm/mpspec.h>
#include <asm/dma.h>
#include <asm/gart.h>
#include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
+
+ /* pre allocte 4k for mptable mpc */
+ early_reserve_e820_mpc_new();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(end_pfn)) {
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_irq.c
+++ linux-2.6/drivers/acpi/pci_irq.c
@@ -570,6 +570,9 @@ int acpi_pci_irq_enable(struct pci_dev *
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+ triggering, polarity);
+
return 0;
}
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
--- linux-2.6.orig/include/asm-x86/mpspec.h
+++ linux-2.6/include/asm-x86/mpspec.h
@@ -41,6 +41,7 @@ extern unsigned long mp_lapic_addr;
extern void find_smp_config(void);
extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
void __cpuinit generic_processor_info(int apicid, int version);
#ifdef CONFIG_ACPI
@@ -49,6 +50,9 @@ extern void mp_override_legacy_irq(u8 bu
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity);
#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -1151,6 +1151,28 @@ int mp_register_gsi(u32 gsi, int trigger
return gsi;
}
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity)
+{
+ struct mpc_config_intsrc intsrc;
+ int ioapic;
+
+ /* print the entry should happen on mptable identically */
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqtype = mp_INT;
+ intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ intsrc.mpc_srcbus = number;
+ intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+ intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+ MP_intsrc_info(&intsrc);
+
+ return 0;
+}
+
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
Index: linux-2.6/arch/x86/kernel/e820.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/e820.c
+++ linux-2.6/arch/x86/kernel/e820.c
@@ -707,3 +707,31 @@ u64 __init find_e820_area_size(u64 start
return -1UL;
}
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+u64 __init early_reserve_e820(u64 sizet, u64 align)
+{
+ u64 start = 0, size = 0;
+ u64 addr;
+
+#ifdef CONFIG_X86_TRAMPOLINE
+ start = TRAMPOLINE_BASE;
+#endif
+ while (size < sizet)
+ start = find_e820_area_size(start, &size, align);
+
+ if (size < sizet)
+ return 0;
+
+ addr = start + size - sizet;
+
+ update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+
+ printk(KERN_INFO "update e820 for early_reserve_e820\n");
+ update_e820();
+
+ return addr;
+}
+
Index: linux-2.6/include/asm-x86/e820.h
===================================================================
--- linux-2.6.orig/include/asm-x86/e820.h
+++ linux-2.6/include/asm-x86/e820.h
@@ -75,6 +75,7 @@ extern u64 find_e820_area_size(u64 start
extern void reserve_early(u64 start, u64 end, char *name);
extern void free_early(u64 start, u64 end);
extern void early_res_to_bootmem(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 sizet, u64 align);
#endif /* __ASSEMBLY__ */
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable v6
2008-05-19 19:52 ` [PATCH] x86: update mptable v5 Yinghai Lu
@ 2008-05-25 23:00 ` Yinghai Lu
2008-06-01 20:17 ` [PATCH] x86: update mptable v7 Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-05-25 23:00 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman
Cc: linux-kernel@vger.kernel.org
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
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -25,6 +25,8 @@
#include <asm/proto.h>
#include <asm/acpi.h>
#include <asm/bios_ebda.h>
+#include <asm/e820.h>
+#include <asm/trampoline.h>
#include <mach_apic.h>
#ifdef CONFIG_X86_32
@@ -161,20 +163,82 @@ static void __init MP_ioapic_info(struct
nr_ioapics++;
}
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init print_MP_intsrc_info(struct mpc_config_intsrc *m)
{
- printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
- mp_irqs[mp_irq_entries].mp_dstapic = m->mpc_dstapic;
- mp_irqs[mp_irq_entries].mp_type = m->mpc_type;
- mp_irqs[mp_irq_entries].mp_irqtype = m->mpc_irqtype;
- mp_irqs[mp_irq_entries].mp_irqflag = m->mpc_irqflag;
- mp_irqs[mp_irq_entries].mp_srcbus = m->mpc_srcbus;
- mp_irqs[mp_irq_entries].mp_srcbusirq = m->mpc_srcbusirq;
- mp_irqs[mp_irq_entries].mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+{
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
+ " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+ (mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+ mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+}
+
+static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
+ struct mp_config_intsrc *mp_irq)
+{
+ mp_irq->mp_dstapic = m->mpc_dstapic;
+ mp_irq->mp_type = m->mpc_type;
+ mp_irq->mp_irqtype = m->mpc_irqtype;
+ mp_irq->mp_irqflag = m->mpc_irqflag;
+ mp_irq->mp_srcbus = m->mpc_srcbus;
+ mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+ mp_irq->mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ m->mpc_dstapic = mp_irq->mp_dstapic;
+ m->mpc_type = mp_irq->mp_type;
+ m->mpc_irqtype = mp_irq->mp_irqtype;
+ m->mpc_irqflag = mp_irq->mp_irqflag;
+ m->mpc_srcbus = mp_irq->mp_srcbus;
+ m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+ m->mpc_dstirq = mp_irq->mp_dstirq;
+}
+
+static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ if (mp_irq->mp_dstapic != m->mpc_dstapic)
+ return 1;
+ if (mp_irq->mp_type != m->mpc_type)
+ return 2;
+ if (mp_irq->mp_irqtype != m->mpc_irqtype)
+ return 3;
+ if (mp_irq->mp_irqflag != m->mpc_irqflag)
+ return 4;
+ if (mp_irq->mp_srcbus != m->mpc_srcbus)
+ return 5;
+ if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+ return 6;
+ if (mp_irq->mp_dstirq != m->mpc_dstirq)
+ return 7;
+
+ return 0;
+}
+
+void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+{
+ int i;
+
+ print_MP_intsrc_info(m);
+
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+ return;
+ }
+
+ assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
@@ -268,12 +332,9 @@ static inline void mps_oem_check(struct
* Read/parse the MPC
*/
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+ char *str)
{
- char str[16];
- char oem[10];
- int count = sizeof(*mpc);
- unsigned char *mpt = ((unsigned char *)mpc) + count;
if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
@@ -301,13 +362,28 @@ static int __init smp_read_mpc(struct mp
memcpy(str, mpc->mpc_productid, 12);
str[12] = 0;
-#ifdef CONFIG_X86_32
- mps_oem_check(mpc, oem, str);
-#endif
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+ char str[16];
+ char oem[10];
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+#ifdef CONFIG_X86_32
+ mps_oem_check(mpc, oem, str);
+#endif
+
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
@@ -785,3 +861,295 @@ void __init find_smp_config(void)
{
__find_smp_config(1);
}
+
+#ifdef CONFIG_X86_IO_APIC
+static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+
+static int __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
+{
+ int i;
+
+ if (m->mpc_irqtype != mp_INT)
+ return 0;
+
+ if (m->mpc_irqflag != 0x0f)
+ return 0;
+
+ /* not legacy */
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (mp_irqs[i].mp_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mp_irqflag != 0x0f)
+ continue;
+
+ if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
+ continue;
+ if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
+ continue;
+ if (irq_used[i]) {
+ /* already claimed */
+ return -2;
+ }
+ irq_used[i] = 1;
+ return i;
+ }
+
+ /* not found */
+ return -1;
+}
+
+#define SPARE_SLOT_NUM 20
+
+static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+#endif
+
+static int __init replace_intsrc_all(struct mp_config_table *mpc,
+ unsigned long mpc_new_phys,
+ unsigned long mpc_new_length)
+{
+#ifdef CONFIG_X86_IO_APIC
+ int i;
+ int nr_m_spare = 0;
+#endif
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
+ while (count < mpc->mpc_length) {
+ switch (*mpt) {
+ case MP_PROCESSOR:
+ {
+ struct mpc_config_processor *m =
+ (struct mpc_config_processor *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ case MP_BUS:
+ {
+ struct mpc_config_bus *m =
+ (struct mpc_config_bus *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ case MP_IOAPIC:
+ {
+ mpt += sizeof(struct mpc_config_ioapic);
+ count += sizeof(struct mpc_config_ioapic);
+ break;
+ }
+ case MP_INTSRC:
+ {
+#ifdef CONFIG_X86_IO_APIC
+ struct mpc_config_intsrc *m =
+ (struct mpc_config_intsrc *)mpt;
+
+ printk(KERN_INFO "OLD ");
+ print_MP_intsrc_info(m);
+ i = get_MP_intsrc_index(m);
+ if (i > 0) {
+ assign_to_mpc_intsrc(&mp_irqs[i], m);
+ printk(KERN_INFO "NEW ");
+ print_mp_irq_info(&mp_irqs[i]);
+ } else if (!i) {
+ /* legacy, do nothing */
+ } else if (nr_m_spare < SPARE_SLOT_NUM) {
+ /*
+ * not found (-1), or duplicated (-2)
+ * are invalid entries,
+ * we need to use the slot later
+ */
+ m_spare[nr_m_spare] = m;
+ nr_m_spare++;
+ }
+#endif
+ mpt += sizeof(struct mpc_config_intsrc);
+ count += sizeof(struct mpc_config_intsrc);
+ break;
+ }
+ case MP_LINTSRC:
+ {
+ struct mpc_config_lintsrc *m =
+ (struct mpc_config_lintsrc *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ default:
+ /* wrong mptable */
+ printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+ printk(KERN_ERR "type %x\n", *mpt);
+ print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
+ 1, mpc, mpc->mpc_length, 1);
+ goto out;
+ }
+ }
+
+#ifdef CONFIG_X86_IO_APIC
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (irq_used[i])
+ continue;
+
+ if (mp_irqs[i].mp_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mp_irqflag != 0x0f)
+ continue;
+
+ if (nr_m_spare > 0) {
+ printk(KERN_INFO "*NEW* found ");
+ nr_m_spare--;
+ assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+ m_spare[nr_m_spare] = NULL;
+ } else {
+ struct mpc_config_intsrc *m =
+ (struct mpc_config_intsrc *)mpt;
+ count += sizeof(struct mpc_config_intsrc);
+ if (!mpc_new_phys) {
+ printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+ } else {
+ if (count <= mpc_new_length)
+ printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
+ else {
+ printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
+ goto out;
+ }
+ }
+ assign_to_mpc_intsrc(&mp_irqs[i], m);
+ mpc->mpc_length = count;
+ mpt += sizeof(struct mpc_config_intsrc);
+ }
+ print_mp_irq_info(&mp_irqs[i]);
+ }
+#endif
+out:
+ /* update checksum */
+ mpc->mpc_checksum = 0;
+ mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
+ mpc->mpc_length);
+
+ return 0;
+}
+
+int __initdata enable_update_mptable;
+
+static int __init update_mptable_setup(char *str)
+{
+ enable_update_mptable = 1;
+ return 0;
+}
+early_param("update_mptable", update_mptable_setup);
+
+static unsigned long __initdata mpc_new_phys;
+static unsigned long mpc_new_length __initdata = 4096;
+
+/* alloc_mptable or alloc_mptable=4k */
+static int __initdata alloc_mptable;
+static int __init parse_alloc_mptable_opt(char *p)
+{
+ enable_update_mptable = 1;
+ alloc_mptable = 1;
+ if (!p)
+ return 0;
+ mpc_new_length = memparse(p, &p);
+ return 0;
+}
+early_param("alloc_mptable", parse_alloc_mptable_opt);
+
+void __init early_reserve_e820_mpc_new(void)
+{
+ if (enable_update_mptable && alloc_mptable) {
+ u64 startt = 0;
+#ifdef CONFIG_X86_TRAMPOLINE
+ startt = TRAMPOLINE_BASE;
+#endif
+ mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4);
+ }
+}
+
+static int __init update_mp_table(void)
+{
+ char str[16];
+ char oem[10];
+ struct intel_mp_floating *mpf;
+ struct mp_config_table *mpc;
+ struct mp_config_table *mpc_new;
+
+ if (!enable_update_mptable)
+ return 0;
+
+ mpf = mpf_found;
+ if (!mpf)
+ return 0;
+
+ /*
+ * Now see if we need to go further.
+ */
+ if (mpf->mpf_feature1 != 0)
+ return 0;
+
+ if (!mpf->mpf_physptr)
+ return 0;
+
+ mpc = phys_to_virt(mpf->mpf_physptr);
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+ printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf));
+ printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+
+ if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
+ mpc_new_phys = 0;
+ printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
+ mpc_new_length);
+ }
+
+ if (!mpc_new_phys) {
+ unsigned char old, new;
+ /* check if we can change the postion */
+ mpc->mpc_checksum = 0;
+ old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+ mpc->mpc_checksum = 0xff;
+ new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+ if (old == new) {
+ printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+ return 0;
+ }
+ printk(KERN_INFO "use in-positon replacing\n");
+ } else {
+ mpf->mpf_physptr = mpc_new_phys;
+ mpc_new = phys_to_virt(mpc_new_phys);
+ memcpy(mpc_new, mpc, mpc->mpc_length);
+ mpc = mpc_new;
+ /* check if we can modify that */
+ if (mpc_new_phys - mpf->mpf_physptr) {
+ struct intel_mp_floating *mpf_new;
+ /* steal 16 bytes from [0, 1k) */
+ printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+ mpf_new = phys_to_virt(0x400 - 16);
+ memcpy(mpf_new, mpf, 16);
+ mpf = mpf_new;
+ mpf->mpf_physptr = mpc_new_phys;
+ }
+ mpf->mpf_checksum = 0;
+ mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16);
+ printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr);
+ }
+
+ /*
+ * only replace the one with mp_INT and
+ * MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
+ * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
+ * may need pci=routeirq for all coverage
+ */
+ replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);
+
+ return 0;
+}
+
+late_initcall(update_mp_table);
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -56,6 +56,7 @@
#include <asm/desc.h>
#include <video/edid.h>
#include <asm/e820.h>
+#include <asm/mpspec.h>
#include <asm/dma.h>
#include <asm/gart.h>
#include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
+
+ /* pre allocte 4k for mptable mpc */
+ early_reserve_e820_mpc_new();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(end_pfn)) {
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_irq.c
+++ linux-2.6/drivers/acpi/pci_irq.c
@@ -570,6 +570,11 @@ int acpi_pci_irq_enable(struct pci_dev *
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+#ifdef CONFIG_X86
+ mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+ triggering, polarity);
+#endif
+
return 0;
}
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
--- linux-2.6.orig/include/asm-x86/mpspec.h
+++ linux-2.6/include/asm-x86/mpspec.h
@@ -39,6 +39,7 @@ extern unsigned long mp_lapic_addr;
extern void find_smp_config(void);
extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
void __cpuinit generic_processor_info(int apicid, int version);
#ifdef CONFIG_ACPI
@@ -47,6 +48,9 @@ extern void mp_override_legacy_irq(u8 bu
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity);
#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -1164,6 +1164,28 @@ int mp_register_gsi(u32 gsi, int trigger
return gsi;
}
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity)
+{
+ struct mpc_config_intsrc intsrc;
+ int ioapic;
+
+ /* print the entry should happen on mptable identically */
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqtype = mp_INT;
+ intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ intsrc.mpc_srcbus = number;
+ intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+ intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+ MP_intsrc_info(&intsrc);
+
+ return 0;
+}
+
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
Index: linux-2.6/arch/x86/kernel/e820.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/e820.c
+++ linux-2.6/arch/x86/kernel/e820.c
@@ -739,3 +739,28 @@ u64 __init find_e820_area_size(u64 start
return -1UL;
}
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
+{
+ u64 size = 0;
+ u64 addr;
+ u64 start;
+
+ start = startt;
+ while (size < sizet)
+ start = find_e820_area_size(start, &size, align);
+
+ if (size < sizet)
+ return 0;
+
+ addr = round_down(start + size - sizet, align);
+ update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+ printk(KERN_INFO "update e820 for early_reserve_e820\n");
+ update_e820();
+
+ return addr;
+}
+
Index: linux-2.6/include/asm-x86/e820.h
===================================================================
--- linux-2.6.orig/include/asm-x86/e820.h
+++ linux-2.6/include/asm-x86/e820.h
@@ -84,6 +84,7 @@ extern u64 find_e820_area_size(u64 start
extern void reserve_early(u64 start, u64 end, char *name);
extern void free_early(u64 start, u64 end);
extern void early_res_to_bootmem(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
#endif /* __ASSEMBLY__ */
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable v7
2008-05-25 23:00 ` [PATCH] x86: update mptable v6 Yinghai Lu
@ 2008-06-01 20:17 ` Yinghai Lu
2008-06-09 2:53 ` [PATCH] x86: update mptable v7 - fix Yinghai Lu
` (2 more replies)
0 siblings, 3 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-01 20:17 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman
Cc: linux-kernel@vger.kernel.org
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
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -25,6 +25,8 @@
#include <asm/proto.h>
#include <asm/acpi.h>
#include <asm/bios_ebda.h>
+#include <asm/e820.h>
+#include <asm/trampoline.h>
#include <mach_apic.h>
#ifdef CONFIG_X86_32
@@ -161,20 +163,81 @@ static void __init MP_ioapic_info(struct
nr_ioapics++;
}
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void print_MP_intsrc_info(struct mpc_config_intsrc *m)
{
- printk(KERN_INFO "Int: type %d, pol %d, trig %d, bus %02x,"
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
m->mpc_irqtype, m->mpc_irqflag & 3,
(m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
- mp_irqs[mp_irq_entries].mp_dstapic = m->mpc_dstapic;
- mp_irqs[mp_irq_entries].mp_type = m->mpc_type;
- mp_irqs[mp_irq_entries].mp_irqtype = m->mpc_irqtype;
- mp_irqs[mp_irq_entries].mp_irqflag = m->mpc_irqflag;
- mp_irqs[mp_irq_entries].mp_srcbus = m->mpc_srcbus;
- mp_irqs[mp_irq_entries].mp_srcbusirq = m->mpc_srcbusirq;
- mp_irqs[mp_irq_entries].mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
+{
+ printk(KERN_CONT "Int: type %d, pol %d, trig %d, bus %02x,"
+ " IRQ %02x, APIC ID %x, APIC INT %02x\n",
+ mp_irq->mp_irqtype, mp_irq->mp_irqflag & 3,
+ (mp_irq->mp_irqflag >> 2) & 3, mp_irq->mp_srcbus,
+ mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
+}
+
+static void assign_to_mp_irq(struct mpc_config_intsrc *m,
+ struct mp_config_intsrc *mp_irq)
+{
+ mp_irq->mp_dstapic = m->mpc_dstapic;
+ mp_irq->mp_type = m->mpc_type;
+ mp_irq->mp_irqtype = m->mpc_irqtype;
+ mp_irq->mp_irqflag = m->mpc_irqflag;
+ mp_irq->mp_srcbus = m->mpc_srcbus;
+ mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
+ mp_irq->mp_dstirq = m->mpc_dstirq;
+}
+
+static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ m->mpc_dstapic = mp_irq->mp_dstapic;
+ m->mpc_type = mp_irq->mp_type;
+ m->mpc_irqtype = mp_irq->mp_irqtype;
+ m->mpc_irqflag = mp_irq->mp_irqflag;
+ m->mpc_srcbus = mp_irq->mp_srcbus;
+ m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
+ m->mpc_dstirq = mp_irq->mp_dstirq;
+}
+
+static int mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+ struct mpc_config_intsrc *m)
+{
+ if (mp_irq->mp_dstapic != m->mpc_dstapic)
+ return 1;
+ if (mp_irq->mp_type != m->mpc_type)
+ return 2;
+ if (mp_irq->mp_irqtype != m->mpc_irqtype)
+ return 3;
+ if (mp_irq->mp_irqflag != m->mpc_irqflag)
+ return 4;
+ if (mp_irq->mp_srcbus != m->mpc_srcbus)
+ return 5;
+ if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+ return 6;
+ if (mp_irq->mp_dstirq != m->mpc_dstirq)
+ return 7;
+
+ return 0;
+}
+
+void MP_intsrc_info(struct mpc_config_intsrc *m)
+{
+ int i;
+
+ print_MP_intsrc_info(m);
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+ return;
+ }
+
+ assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
panic("Max # of irq sources exceeded!!\n");
}
@@ -268,12 +331,9 @@ static inline void mps_oem_check(struct
* Read/parse the MPC
*/
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
+ char *str)
{
- char str[16];
- char oem[10];
- int count = sizeof(*mpc);
- unsigned char *mpt = ((unsigned char *)mpc) + count;
if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
@@ -301,13 +361,28 @@ static int __init smp_read_mpc(struct mp
memcpy(str, mpc->mpc_productid, 12);
str[12] = 0;
-#ifdef CONFIG_X86_32
- mps_oem_check(mpc, oem, str);
-#endif
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ return 1;
+}
+
+static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+{
+ char str[16];
+ char oem[10];
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+#ifdef CONFIG_X86_32
+ mps_oem_check(mpc, oem, str);
+#endif
+
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
mp_lapic_addr = mpc->mpc_lapic;
@@ -785,3 +860,295 @@ void __init find_smp_config(void)
{
__find_smp_config(1);
}
+
+#ifdef CONFIG_X86_IO_APIC
+static u8 __initdata irq_used[MAX_IRQ_SOURCES];
+
+static int __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
+{
+ int i;
+
+ if (m->mpc_irqtype != mp_INT)
+ return 0;
+
+ if (m->mpc_irqflag != 0x0f)
+ return 0;
+
+ /* not legacy */
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (mp_irqs[i].mp_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mp_irqflag != 0x0f)
+ continue;
+
+ if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
+ continue;
+ if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
+ continue;
+ if (irq_used[i]) {
+ /* already claimed */
+ return -2;
+ }
+ irq_used[i] = 1;
+ return i;
+ }
+
+ /* not found */
+ return -1;
+}
+
+#define SPARE_SLOT_NUM 20
+
+static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+#endif
+
+static int __init replace_intsrc_all(struct mp_config_table *mpc,
+ unsigned long mpc_new_phys,
+ unsigned long mpc_new_length)
+{
+#ifdef CONFIG_X86_IO_APIC
+ int i;
+ int nr_m_spare = 0;
+#endif
+
+ int count = sizeof(*mpc);
+ unsigned char *mpt = ((unsigned char *)mpc) + count;
+
+ printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
+ while (count < mpc->mpc_length) {
+ switch (*mpt) {
+ case MP_PROCESSOR:
+ {
+ struct mpc_config_processor *m =
+ (struct mpc_config_processor *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ case MP_BUS:
+ {
+ struct mpc_config_bus *m =
+ (struct mpc_config_bus *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ case MP_IOAPIC:
+ {
+ mpt += sizeof(struct mpc_config_ioapic);
+ count += sizeof(struct mpc_config_ioapic);
+ break;
+ }
+ case MP_INTSRC:
+ {
+#ifdef CONFIG_X86_IO_APIC
+ struct mpc_config_intsrc *m =
+ (struct mpc_config_intsrc *)mpt;
+
+ printk(KERN_INFO "OLD ");
+ print_MP_intsrc_info(m);
+ i = get_MP_intsrc_index(m);
+ if (i > 0) {
+ assign_to_mpc_intsrc(&mp_irqs[i], m);
+ printk(KERN_INFO "NEW ");
+ print_mp_irq_info(&mp_irqs[i]);
+ } else if (!i) {
+ /* legacy, do nothing */
+ } else if (nr_m_spare < SPARE_SLOT_NUM) {
+ /*
+ * not found (-1), or duplicated (-2)
+ * are invalid entries,
+ * we need to use the slot later
+ */
+ m_spare[nr_m_spare] = m;
+ nr_m_spare++;
+ }
+#endif
+ mpt += sizeof(struct mpc_config_intsrc);
+ count += sizeof(struct mpc_config_intsrc);
+ break;
+ }
+ case MP_LINTSRC:
+ {
+ struct mpc_config_lintsrc *m =
+ (struct mpc_config_lintsrc *)mpt;
+ mpt += sizeof(*m);
+ count += sizeof(*m);
+ break;
+ }
+ default:
+ /* wrong mptable */
+ printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
+ printk(KERN_ERR "type %x\n", *mpt);
+ print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
+ 1, mpc, mpc->mpc_length, 1);
+ goto out;
+ }
+ }
+
+#ifdef CONFIG_X86_IO_APIC
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (irq_used[i])
+ continue;
+
+ if (mp_irqs[i].mp_irqtype != mp_INT)
+ continue;
+
+ if (mp_irqs[i].mp_irqflag != 0x0f)
+ continue;
+
+ if (nr_m_spare > 0) {
+ printk(KERN_INFO "*NEW* found ");
+ nr_m_spare--;
+ assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
+ m_spare[nr_m_spare] = NULL;
+ } else {
+ struct mpc_config_intsrc *m =
+ (struct mpc_config_intsrc *)mpt;
+ count += sizeof(struct mpc_config_intsrc);
+ if (!mpc_new_phys) {
+ printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
+ } else {
+ if (count <= mpc_new_length)
+ printk(KERN_INFO "No spare slots, try to append..., new mpc_length %x\n", count);
+ else {
+ printk(KERN_ERR "mpc_new_length %lx is too small\n", mpc_new_length);
+ goto out;
+ }
+ }
+ assign_to_mpc_intsrc(&mp_irqs[i], m);
+ mpc->mpc_length = count;
+ mpt += sizeof(struct mpc_config_intsrc);
+ }
+ print_mp_irq_info(&mp_irqs[i]);
+ }
+#endif
+out:
+ /* update checksum */
+ mpc->mpc_checksum = 0;
+ mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
+ mpc->mpc_length);
+
+ return 0;
+}
+
+int __initdata enable_update_mptable;
+
+static int __init update_mptable_setup(char *str)
+{
+ enable_update_mptable = 1;
+ return 0;
+}
+early_param("update_mptable", update_mptable_setup);
+
+static unsigned long __initdata mpc_new_phys;
+static unsigned long mpc_new_length __initdata = 4096;
+
+/* alloc_mptable or alloc_mptable=4k */
+static int __initdata alloc_mptable;
+static int __init parse_alloc_mptable_opt(char *p)
+{
+ enable_update_mptable = 1;
+ alloc_mptable = 1;
+ if (!p)
+ return 0;
+ mpc_new_length = memparse(p, &p);
+ return 0;
+}
+early_param("alloc_mptable", parse_alloc_mptable_opt);
+
+void __init early_reserve_e820_mpc_new(void)
+{
+ if (enable_update_mptable && alloc_mptable) {
+ u64 startt = 0;
+#ifdef CONFIG_X86_TRAMPOLINE
+ startt = TRAMPOLINE_BASE;
+#endif
+ mpc_new_phys = early_reserve_e820(startt, mpc_new_length, 4);
+ }
+}
+
+static int __init update_mp_table(void)
+{
+ char str[16];
+ char oem[10];
+ struct intel_mp_floating *mpf;
+ struct mp_config_table *mpc;
+ struct mp_config_table *mpc_new;
+
+ if (!enable_update_mptable)
+ return 0;
+
+ mpf = mpf_found;
+ if (!mpf)
+ return 0;
+
+ /*
+ * Now see if we need to go further.
+ */
+ if (mpf->mpf_feature1 != 0)
+ return 0;
+
+ if (!mpf->mpf_physptr)
+ return 0;
+
+ mpc = phys_to_virt(mpf->mpf_physptr);
+
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+ printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf));
+ printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
+
+ if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
+ mpc_new_phys = 0;
+ printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
+ mpc_new_length);
+ }
+
+ if (!mpc_new_phys) {
+ unsigned char old, new;
+ /* check if we can change the postion */
+ mpc->mpc_checksum = 0;
+ old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+ mpc->mpc_checksum = 0xff;
+ new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+ if (old == new) {
+ printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
+ return 0;
+ }
+ printk(KERN_INFO "use in-positon replacing\n");
+ } else {
+ mpf->mpf_physptr = mpc_new_phys;
+ mpc_new = phys_to_virt(mpc_new_phys);
+ memcpy(mpc_new, mpc, mpc->mpc_length);
+ mpc = mpc_new;
+ /* check if we can modify that */
+ if (mpc_new_phys - mpf->mpf_physptr) {
+ struct intel_mp_floating *mpf_new;
+ /* steal 16 bytes from [0, 1k) */
+ printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
+ mpf_new = phys_to_virt(0x400 - 16);
+ memcpy(mpf_new, mpf, 16);
+ mpf = mpf_new;
+ mpf->mpf_physptr = mpc_new_phys;
+ }
+ mpf->mpf_checksum = 0;
+ mpf->mpf_checksum -= mpf_checksum((unsigned char *)mpf, 16);
+ printk(KERN_INFO "mpf_physptr new: %x\n", mpf->mpf_physptr);
+ }
+
+ /*
+ * only replace the one with mp_INT and
+ * MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
+ * already in mp_irqs , stored by ... and mp_config_acpi_gsi,
+ * may need pci=routeirq for all coverage
+ */
+ replace_intsrc_all(mpc, mpc_new_phys, mpc_new_length);
+
+ return 0;
+}
+
+late_initcall(update_mp_table);
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -56,6 +56,7 @@
#include <asm/desc.h>
#include <video/edid.h>
#include <asm/e820.h>
+#include <asm/mpspec.h>
#include <asm/dma.h>
#include <asm/gart.h>
#include <asm/mpspec.h>
@@ -373,6 +374,9 @@ void __init setup_arch(char **cmdline_p)
* we are rounding upwards:
*/
end_pfn = e820_end_of_ram();
+
+ /* pre allocte 4k for mptable mpc */
+ early_reserve_e820_mpc_new();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(end_pfn)) {
Index: linux-2.6/drivers/acpi/pci_irq.c
===================================================================
--- linux-2.6.orig/drivers/acpi/pci_irq.c
+++ linux-2.6/drivers/acpi/pci_irq.c
@@ -570,6 +570,11 @@ int acpi_pci_irq_enable(struct pci_dev *
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+#ifdef CONFIG_X86
+ mp_config_acpi_gsi(dev->bus->number, dev->devfn, dev->pin, irq,
+ triggering, polarity);
+#endif
+
return 0;
}
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
--- linux-2.6.orig/include/asm-x86/mpspec.h
+++ linux-2.6/include/asm-x86/mpspec.h
@@ -39,6 +39,7 @@ extern unsigned long mp_lapic_addr;
extern void find_smp_config(void);
extern void get_smp_config(void);
+extern void early_reserve_e820_mpc_new(void);
void __cpuinit generic_processor_info(int apicid, int version);
#ifdef CONFIG_ACPI
@@ -47,6 +48,9 @@ extern void mp_override_legacy_irq(u8 bu
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
+extern void MP_intsrc_info(struct mpc_config_intsrc *m);
+extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity);
#endif /* CONFIG_ACPI */
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -1164,6 +1164,28 @@ int mp_register_gsi(u32 gsi, int trigger
return gsi;
}
+int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
+ u32 gsi, int triggering, int polarity)
+{
+ struct mpc_config_intsrc intsrc;
+ int ioapic;
+
+ /* print the entry should happen on mptable identically */
+ intsrc.mpc_type = MP_INTSRC;
+ intsrc.mpc_irqtype = mp_INT;
+ intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ (polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
+ intsrc.mpc_srcbus = number;
+ intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ ioapic = mp_find_ioapic(gsi);
+ intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
+ intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+
+ MP_intsrc_info(&intsrc);
+
+ return 0;
+}
+
/*
* Parse IOAPIC related entries in MADT
* returns 0 on success, < 0 on error
Index: linux-2.6/arch/x86/kernel/e820.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/e820.c
+++ linux-2.6/arch/x86/kernel/e820.c
@@ -739,3 +739,28 @@ u64 __init find_e820_area_size(u64 start
return -1UL;
}
+
+/*
+ * pre allocated 4k and reserved it in e820
+ */
+u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align)
+{
+ u64 size = 0;
+ u64 addr;
+ u64 start;
+
+ start = startt;
+ while (size < sizet)
+ start = find_e820_area_size(start, &size, align);
+
+ if (size < sizet)
+ return 0;
+
+ addr = round_down(start + size - sizet, align);
+ update_memory_range(addr, sizet, E820_RAM, E820_RESERVED);
+ printk(KERN_INFO "update e820 for early_reserve_e820\n");
+ update_e820();
+
+ return addr;
+}
+
Index: linux-2.6/include/asm-x86/e820.h
===================================================================
--- linux-2.6.orig/include/asm-x86/e820.h
+++ linux-2.6/include/asm-x86/e820.h
@@ -84,6 +84,7 @@ extern u64 find_e820_area_size(u64 start
extern void reserve_early(u64 start, u64 end, char *name);
extern void free_early(u64 start, u64 end);
extern void early_res_to_bootmem(u64 start, u64 end);
+extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align);
#endif /* __ASSEMBLY__ */
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable v7 - fix
2008-06-01 20:17 ` [PATCH] x86: update mptable v7 Yinghai Lu
@ 2008-06-09 2:53 ` Yinghai Lu
2008-06-09 10:13 ` Ingo Molnar
2008-06-18 21:32 ` [PATCH] x86: update mptable fix with no ioapic Yinghai Lu
2008-06-18 22:18 ` [PATCH] x86: update mptable v7 Len Brown
2 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-09 2:53 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman
Cc: linux-kernel@vger.kernel.org
[PATCH] x86: update mptable v7 - fix
need to call early_reserve_e820 to prelocate mptable for 32bit
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Index: linux-2.6/arch/x86/kernel/setup_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_32.c
+++ linux-2.6/arch/x86/kernel/setup_32.c
@@ -761,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
*/
max_pfn = e820_end_of_ram();
+ /* pre allocte 4k for mptable mpc */
+ early_reserve_e820_mpc_new();
/* update e820 for memory not covered by WB MTRRs */
mtrr_bp_init();
if (mtrr_trim_uncached_memory(max_pfn)) {
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7 - fix
2008-06-09 2:53 ` [PATCH] x86: update mptable v7 - fix Yinghai Lu
@ 2008-06-09 10:13 ` Ingo Molnar
2008-06-09 17:51 ` Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: Ingo Molnar @ 2008-06-09 10:13 UTC (permalink / raw)
To: Yinghai Lu
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Eric W. Biederman,
linux-kernel@vger.kernel.org
* Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> [PATCH] x86: update mptable v7 - fix
>
> need to call early_reserve_e820 to prelocate mptable for 32bit
>
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
>
> Index: linux-2.6/arch/x86/kernel/setup_32.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/setup_32.c
> +++ linux-2.6/arch/x86/kernel/setup_32.c
> @@ -761,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
> */
> max_pfn = e820_end_of_ram();
>
> + /* pre allocte 4k for mptable mpc */
> + early_reserve_e820_mpc_new();
applied, thanks. It needed the small build fix below as well, for UP
32-bit.
Ingo
--------------->
commit 3c803fb3e1972566f7a1613f53f7e5a70fbde83f
Author: Ingo Molnar <mingo@elte.hu>
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'
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/include/asm-x86/mpspec.h b/include/asm-x86/mpspec.h
index 6e9c958..b8ba374 100644
--- a/include/asm-x86/mpspec.h
+++ b/include/asm-x86/mpspec.h
@@ -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
^ permalink raw reply related [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7 - fix
2008-06-09 10:13 ` Ingo Molnar
@ 2008-06-09 17:51 ` Yinghai Lu
2008-06-09 18:11 ` Maciej W. Rozycki
2008-06-09 19:09 ` Ingo Molnar
0 siblings, 2 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-09 17:51 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Eric W. Biederman,
linux-kernel@vger.kernel.org
On Mon, Jun 9, 2008 at 3:13 AM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
>
>> [PATCH] x86: update mptable v7 - fix
>>
>> need to call early_reserve_e820 to prelocate mptable for 32bit
>>
>> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
>>
>> Index: linux-2.6/arch/x86/kernel/setup_32.c
>> ===================================================================
>> --- linux-2.6.orig/arch/x86/kernel/setup_32.c
>> +++ linux-2.6/arch/x86/kernel/setup_32.c
>> @@ -761,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
>> */
>> max_pfn = e820_end_of_ram();
>>
>> + /* pre allocte 4k for mptable mpc */
>> + early_reserve_e820_mpc_new();
>
> applied, thanks. It needed the small build fix below as well, for UP
> 32-bit.
>
> Ingo
>
> --------------->
> commit 3c803fb3e1972566f7a1613f53f7e5a70fbde83f
> Author: Ingo Molnar <mingo@elte.hu>
> 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'
>
> Signed-off-by: Ingo Molnar <mingo@elte.hu>
>
> diff --git a/include/asm-x86/mpspec.h b/include/asm-x86/mpspec.h
> index 6e9c958..b8ba374 100644
> --- a/include/asm-x86/mpspec.h
> +++ b/include/asm-x86/mpspec.h
> @@ -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
thanks. So X86_MPPARSE is not needed when SMP is not enabled?
YH
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7 - fix
2008-06-09 17:51 ` Yinghai Lu
@ 2008-06-09 18:11 ` Maciej W. Rozycki
2008-06-09 19:09 ` Ingo Molnar
1 sibling, 0 replies; 65+ messages in thread
From: Maciej W. Rozycki @ 2008-06-09 18:11 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
On Mon, 9 Jun 2008, Yinghai Lu wrote:
> thanks. So X86_MPPARSE is not needed when SMP is not enabled?
X86_MPPARSE should depend on X86_LOCAL_APIC and you can still have it
enabled while !SMP. I think current dependencies express it quite
clearly.
Maciej
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7 - fix
2008-06-09 17:51 ` Yinghai Lu
2008-06-09 18:11 ` Maciej W. Rozycki
@ 2008-06-09 19:09 ` Ingo Molnar
2008-06-09 19:38 ` Yinghai Lu
2008-06-09 19:49 ` Maciej W. Rozycki
1 sibling, 2 replies; 65+ messages in thread
From: Ingo Molnar @ 2008-06-09 19:09 UTC (permalink / raw)
To: Yinghai Lu
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Eric W. Biederman,
linux-kernel@vger.kernel.org
* Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> thanks. So X86_MPPARSE is not needed when SMP is not enabled?
here's the condition:
config X86_MPPARSE
def_bool y
depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
64-bit has it unconditionally, 32-bit has it on SMP, UP-IOAPIC or
UP-local-APIC mode. [ (and VISWS is an ugly complication we should try
to eradicate similarly to NUMAQ, if possible :-) ]
Ingo
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7 - fix
2008-06-09 19:09 ` Ingo Molnar
@ 2008-06-09 19:38 ` Yinghai Lu
2008-06-09 19:46 ` H. Peter Anvin
2008-06-09 19:49 ` Maciej W. Rozycki
1 sibling, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-09 19:38 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Eric W. Biederman,
linux-kernel@vger.kernel.org
On Mon, Jun 9, 2008 at 12:09 PM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
>
>> thanks. So X86_MPPARSE is not needed when SMP is not enabled?
>
> here's the condition:
>
> config X86_MPPARSE
> def_bool y
> depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
>
> 64-bit has it unconditionally, 32-bit has it on SMP, UP-IOAPIC or
> UP-local-APIC mode. [ (and VISWS is an ugly complication we should try
> to eradicate similarly to NUMAQ, if possible :-) ]
VISWS or VOYAGER depends on !PCI, that is some odd system.
YH
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7 - fix
2008-06-09 19:38 ` Yinghai Lu
@ 2008-06-09 19:46 ` H. Peter Anvin
0 siblings, 0 replies; 65+ messages in thread
From: H. Peter Anvin @ 2008-06-09 19:46 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Thomas Gleixner, Andrew Morton, Eric W. Biederman,
linux-kernel@vger.kernel.org
Yinghai Lu wrote:
>
> VISWS or VOYAGER depends on !PCI, that is some odd system.
>
Both are long-since obsolete systems.
-hpa
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7 - fix
2008-06-09 19:09 ` Ingo Molnar
2008-06-09 19:38 ` Yinghai Lu
@ 2008-06-09 19:49 ` Maciej W. Rozycki
1 sibling, 0 replies; 65+ messages in thread
From: Maciej W. Rozycki @ 2008-06-09 19:49 UTC (permalink / raw)
To: Ingo Molnar
Cc: Yinghai Lu, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
On Mon, 9 Jun 2008, Ingo Molnar wrote:
> here's the condition:
>
> config X86_MPPARSE
> def_bool y
> depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
>
> 64-bit has it unconditionally, 32-bit has it on SMP, UP-IOAPIC or
> UP-local-APIC mode. [ (and VISWS is an ugly complication we should try
> to eradicate similarly to NUMAQ, if possible :-) ]
Given X86_64 selects X86_LOCAL_APIC I am not sure the redundancy seen
above does not actually obscure the logic behind... I think:
depends on X86_LOCAL_APIC && !X86_VISWS
would be clearer and get the same.
Maciej
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable fix with no ioapic
2008-06-01 20:17 ` [PATCH] x86: update mptable v7 Yinghai Lu
2008-06-09 2:53 ` [PATCH] x86: update mptable v7 - fix Yinghai Lu
@ 2008-06-18 21:32 ` Yinghai Lu
2008-06-19 0:29 ` [PATCH] x86: update mptable fix with no ioapic v2 Yinghai Lu
2008-06-18 22:18 ` [PATCH] x86: update mptable v7 Len Brown
2 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-18 21:32 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
Cc: Daniel Exner, linux-kernel@vger.kernel.org
if the system doesn't have ioapic, we don't need to store entries for mptable
update
Reported-by: Daniel Exner <dex@dragonslave.de>
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 04dbb35..e639d2f 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -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;
^ permalink raw reply related [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-01 20:17 ` [PATCH] x86: update mptable v7 Yinghai Lu
2008-06-09 2:53 ` [PATCH] x86: update mptable v7 - fix Yinghai Lu
2008-06-18 21:32 ` [PATCH] x86: update mptable fix with no ioapic Yinghai Lu
@ 2008-06-18 22:18 ` Len Brown
2008-06-18 22:32 ` Yinghai Lu
2 siblings, 1 reply; 65+ messages in thread
From: Len Brown @ 2008-06-18 22:18 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
On Sun, 1 Jun 2008, Yinghai Lu wrote:
>
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-18 22:18 ` [PATCH] x86: update mptable v7 Len Brown
@ 2008-06-18 22:32 ` Yinghai Lu
2008-06-19 0:33 ` Len Brown
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-18 22:32 UTC (permalink / raw)
To: Len Brown
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
On Wed, Jun 18, 2008 at 3:18 PM, Len Brown <lenb@kernel.org> wrote:
>
>
> On Sun, 1 Jun 2008, Yinghai Lu wrote:
>
>>
>> make mptable to be consistent to acpi routing, so we could
>> 1. kexec kernel with acpi=off
>> 2. workaround BIOS that acpi routing is working, but mptable is not right.
>> so can use kernel/kexec to start other os that doesn't have good acpi support
>
> Is this an effort to boot an ACPI-mode kernel,
> and then kexec a non-ACPI kernel?
Yes,
>
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: update mptable fix with no ioapic v2
2008-06-18 21:32 ` [PATCH] x86: update mptable fix with no ioapic Yinghai Lu
@ 2008-06-19 0:29 ` Yinghai Lu
2008-06-19 7:18 ` [PATCH] x86: let MPS support selectable Yinghai Lu
2008-06-19 12:13 ` [PATCH] x86: update mptable fix with no ioapic v2 Ingo Molnar
0 siblings, 2 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 0:29 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Daniel Exner, Len Brown
Cc: linux-kernel@vger.kernel.org
if the system doesn't have ioapic, we don't need to store entries for mptable
update
also let mp_config_acpi_gsi not call func in mpparse
so later could decouple mpparse with acpi more easily
Reported-by: Daniel Exner <dex@dragonslave.de>
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
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(-)
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -958,10 +958,37 @@ void __init mp_register_ioapic(int id, u
nr_ioapics++;
}
+static void assign_to_mp_irq(struct mp_config_intsrc *m,
+ struct mp_config_intsrc *mp_irq)
+{
+ memcpy(mp_irq, m, sizeof(struct mp_config_intsrc));
+}
+
+static int mp_irq_cmp(struct mp_config_intsrc *mp_irq,
+ struct mp_config_intsrc *m)
+{
+ return memcmp(mp_irq, m, sizeof(struct mp_config_intsrc));
+}
+
+static void save_mp_irq(struct mp_config_intsrc *m)
+{
+ int i;
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (!mp_irq_cmp(&mp_irqs[i], m))
+ return;
+ }
+
+ assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
+ if (++mp_irq_entries == MAX_IRQ_SOURCES)
+ panic("Max # of irq sources exceeded!!\n");
+}
+
void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
{
int ioapic;
int pin;
+ struct mp_config_intsrc mp_irq;
/*
* Convert 'gsi' to 'ioapic.pin'.
@@ -979,18 +1006,15 @@ void __init mp_override_legacy_irq(u8 bu
if ((bus_irq == 0) && (trigger == 3))
trigger = 1;
- mp_irqs[mp_irq_entries].mp_type = MP_INTSRC;
- mp_irqs[mp_irq_entries].mp_irqtype = mp_INT;
- mp_irqs[mp_irq_entries].mp_irqflag = (trigger << 2) | polarity;
- mp_irqs[mp_irq_entries].mp_srcbus = MP_ISA_BUS;
- mp_irqs[mp_irq_entries].mp_srcbusirq = bus_irq; /* IRQ */
- mp_irqs[mp_irq_entries].mp_dstapic =
- mp_ioapics[ioapic].mp_apicid; /* APIC ID */
- mp_irqs[mp_irq_entries].mp_dstirq = pin; /* INTIN# */
-
- if (++mp_irq_entries == MAX_IRQ_SOURCES)
- panic("Max # of irq sources exceeded!!\n");
+ mp_irq.mp_type = MP_INTSRC;
+ mp_irq.mp_irqtype = mp_INT;
+ mp_irq.mp_irqflag = (trigger << 2) | polarity;
+ mp_irq.mp_srcbus = MP_ISA_BUS;
+ mp_irq.mp_srcbusirq = bus_irq; /* IRQ */
+ mp_irq.mp_dstapic = mp_ioapics[ioapic].mp_apicid; /* APIC ID */
+ mp_irq.mp_dstirq = pin; /* INTIN# */
+ save_mp_irq(&mp_irq);
}
void __init mp_config_acpi_legacy_irqs(void)
@@ -998,6 +1022,7 @@ void __init mp_config_acpi_legacy_irqs(v
int i;
int ioapic;
unsigned int dstapic;
+ struct mp_config_intsrc mp_irq;
#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
/*
@@ -1050,16 +1075,15 @@ void __init mp_config_acpi_legacy_irqs(v
continue; /* IRQ already used */
}
- mp_irqs[mp_irq_entries].mp_type = MP_INTSRC;
- mp_irqs[mp_irq_entries].mp_irqflag = 0; /* Conforming */
- mp_irqs[mp_irq_entries].mp_srcbus = MP_ISA_BUS;
- mp_irqs[mp_irq_entries].mp_dstapic = dstapic;
- mp_irqs[mp_irq_entries].mp_irqtype = mp_INT;
- mp_irqs[mp_irq_entries].mp_srcbusirq = i; /* Identity mapped */
- mp_irqs[mp_irq_entries].mp_dstirq = i;
+ mp_irq.mp_type = MP_INTSRC;
+ mp_irq.mp_irqflag = 0; /* Conforming */
+ mp_irq.mp_srcbus = MP_ISA_BUS;
+ mp_irq.mp_dstapic = dstapic;
+ mp_irq.mp_irqtype = mp_INT;
+ mp_irq.mp_srcbusirq = i; /* Identity mapped */
+ mp_irq.mp_dstirq = i;
- if (++mp_irq_entries == MAX_IRQ_SOURCES)
- panic("Max # of irq sources exceeded!!\n");
+ save_mp_irq(&mp_irq);
}
}
@@ -1167,25 +1191,26 @@ int mp_register_gsi(u32 gsi, int trigger
int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
u32 gsi, int triggering, int polarity)
{
- struct mpc_config_intsrc intsrc;
+#ifdef CONFIG_X86_MPPARSE
+ struct mp_config_intsrc mp_irq;
int ioapic;
- if (!enable_update_mptable)
+ if (!acpi_ioapic)
return 0;
/* print the entry should happen on mptable identically */
- intsrc.mpc_type = MP_INTSRC;
- intsrc.mpc_irqtype = mp_INT;
- intsrc.mpc_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
+ mp_irq.mp_type = MP_INTSRC;
+ mp_irq.mp_irqtype = mp_INT;
+ mp_irq.mp_irqflag = (triggering == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
- intsrc.mpc_srcbus = number;
- intsrc.mpc_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
+ mp_irq.mp_srcbus = number;
+ mp_irq.mp_srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
ioapic = mp_find_ioapic(gsi);
- intsrc.mpc_dstapic = mp_ioapic_routing[ioapic].apic_id;
- intsrc.mpc_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
-
- MP_intsrc_info(&intsrc);
+ mp_irq.mp_dstapic = mp_ioapic_routing[ioapic].apic_id;
+ mp_irq.mp_dstirq = gsi - mp_ioapic_routing[ioapic].gsi_base;
+ save_mp_irq(&mp_irq);
+#endif
return 0;
}
Index: linux-2.6/arch/x86/kernel/mpparse.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6/arch/x86/kernel/mpparse.c
@@ -34,8 +34,6 @@
#include <mach_mpparse.h>
#endif
-int enable_update_mptable;
-
/*
* Checksum an MP configuration block.
*/
@@ -246,7 +244,7 @@ static void __init print_mp_irq_info(str
mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
}
-static void assign_to_mp_irq(struct mpc_config_intsrc *m,
+static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
struct mp_config_intsrc *mp_irq)
{
mp_irq->mp_dstapic = m->mpc_dstapic;
@@ -270,7 +268,7 @@ static void __init assign_to_mpc_intsrc(
m->mpc_dstirq = mp_irq->mp_dstirq;
}
-static int mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
+static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
struct mpc_config_intsrc *m)
{
if (mp_irq->mp_dstapic != m->mpc_dstapic)
@@ -291,17 +289,16 @@ static int mp_irq_mpc_intsrc_cmp(struct
return 0;
}
-void MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
{
int i;
print_MP_intsrc_info(m);
- if (enable_update_mptable)
- for (i = 0; i < mp_irq_entries; i++) {
- if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
- return;
- }
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (!mp_irq_mpc_intsrc_cmp(&mp_irqs[i], m))
+ return;
+ }
assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
if (++mp_irq_entries == MAX_IRQ_SOURCES)
@@ -1113,6 +1110,8 @@ out:
return 0;
}
+static int __initdata enable_update_mptable;
+
static int __init update_mptable_setup(char *str)
{
enable_update_mptable = 1;
Index: linux-2.6/include/asm-x86/mpspec.h
===================================================================
--- linux-2.6.orig/include/asm-x86/mpspec.h
+++ linux-2.6/include/asm-x86/mpspec.h
@@ -59,9 +59,7 @@ extern void mp_override_legacy_irq(u8 bu
u32 gsi);
extern void mp_config_acpi_legacy_irqs(void);
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
-extern void MP_intsrc_info(struct mpc_config_intsrc *m);
#ifdef CONFIG_X86_IO_APIC
-extern int enable_update_mptable;
extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
u32 gsi, int triggering, int polarity);
#else
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-18 22:32 ` Yinghai Lu
@ 2008-06-19 0:33 ` Len Brown
2008-06-19 0:49 ` Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: Len Brown @ 2008-06-19 0:33 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
On Wed, 18 Jun 2008, Yinghai Lu wrote:
> On Wed, Jun 18, 2008 at 3:18 PM, Len Brown <lenb@kernel.org> wrote:
> >
> >
> > On Sun, 1 Jun 2008, Yinghai Lu wrote:
> >
> >>
> >> make mptable to be consistent to acpi routing, so we could
> >> 1. kexec kernel with acpi=off
> >> 2. workaround BIOS that acpi routing is working, but mptable is not right.
> >> so can use kernel/kexec to start other os that doesn't have good acpi support
> >
> > Is this an effort to boot an ACPI-mode kernel,
> > and then kexec a non-ACPI kernel?
>
> Yes,
Why is this feature needed?
There are a number of ways that the resulting kernel may fail,
all platform specific.
> >
> > 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 0:33 ` Len Brown
@ 2008-06-19 0:49 ` Yinghai Lu
2008-06-19 4:32 ` Eric W. Biederman
2008-06-19 5:20 ` Len Brown
0 siblings, 2 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 0:49 UTC (permalink / raw)
To: Len Brown
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
On Wed, Jun 18, 2008 at 5:33 PM, Len Brown <lenb@kernel.org> wrote:
>
>
> On Wed, 18 Jun 2008, Yinghai Lu wrote:
>
>> On Wed, Jun 18, 2008 at 3:18 PM, Len Brown <lenb@kernel.org> wrote:
>> >
>> >
>> > On Sun, 1 Jun 2008, Yinghai Lu wrote:
>> >
>> >>
>> >> make mptable to be consistent to acpi routing, so we could
>> >> 1. kexec kernel with acpi=off
>> >> 2. workaround BIOS that acpi routing is working, but mptable is not right.
>> >> so can use kernel/kexec to start other os that doesn't have good acpi support
>> >
>> > Is this an effort to boot an ACPI-mode kernel,
>> > and then kexec a non-ACPI kernel?
>>
>> Yes,
>
> Why is this feature needed?
> There are a number of ways that the resulting kernel may fail,
> all platform specific.
other os still doesn't have update acpi irq routing support. but has
broken mptable.
>
>> >
>> > 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.
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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 0:49 ` Yinghai Lu
@ 2008-06-19 4:32 ` Eric W. Biederman
2008-06-19 5:09 ` H. Peter Anvin
` (2 more replies)
2008-06-19 5:20 ` Len Brown
1 sibling, 3 replies; 65+ messages in thread
From: Eric W. Biederman @ 2008-06-19 4:32 UTC (permalink / raw)
To: Yinghai Lu
Cc: Len Brown, Ingo Molnar, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, linux-kernel@vger.kernel.org
"Yinghai Lu" <yhlu.kernel@gmail.com> writes:
> On Wed, Jun 18, 2008 at 5:33 PM, Len Brown <lenb@kernel.org> wrote:
>>
>>
>> On Wed, 18 Jun 2008, Yinghai Lu wrote:
>>
>>> On Wed, Jun 18, 2008 at 3:18 PM, Len Brown <lenb@kernel.org> wrote:
>>> >
>>> >
>>> > On Sun, 1 Jun 2008, Yinghai Lu wrote:
>>> >
>>> >>
>>> >> make mptable to be consistent to acpi routing, so we could
>>> >> 1. kexec kernel with acpi=off
>>> >> 2. workaround BIOS that acpi routing is working, but mptable is not right.
>>> >> so can use kernel/kexec to start other os that doesn't have good acpi
> support
>>> >
>>> > Is this an effort to boot an ACPI-mode kernel,
>>> > and then kexec a non-ACPI kernel?
>>>
>>> Yes,
>>
>> Why is this feature needed?
>> There are a number of ways that the resulting kernel may fail,
>> all platform specific.
>
> 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.
>>> > 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.
>
> 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.
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 4:32 ` Eric W. Biederman
@ 2008-06-19 5:09 ` H. Peter Anvin
2008-06-19 5:11 ` Yinghai Lu
2008-06-19 5:27 ` Len Brown
2 siblings, 0 replies; 65+ messages in thread
From: H. Peter Anvin @ 2008-06-19 5:09 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Yinghai Lu, Len Brown, Ingo Molnar, Thomas Gleixner,
Andrew Morton, linux-kernel@vger.kernel.org
Eric W. Biederman wrote:
>
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 4:32 ` Eric W. Biederman
2008-06-19 5:09 ` H. Peter Anvin
@ 2008-06-19 5:11 ` Yinghai Lu
2008-06-19 5:27 ` Len Brown
2 siblings, 0 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 5:11 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Len Brown, Ingo Molnar, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, linux-kernel@vger.kernel.org
On Wed, Jun 18, 2008 at 9:32 PM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
> "Yinghai Lu" <yhlu.kernel@gmail.com> writes:
>
>> On Wed, Jun 18, 2008 at 5:33 PM, Len Brown <lenb@kernel.org> wrote:
>>>
>>>
>>> On Wed, 18 Jun 2008, Yinghai Lu wrote:
>>>
>>>> On Wed, Jun 18, 2008 at 3:18 PM, Len Brown <lenb@kernel.org> wrote:
>>>> >
>>>> >
>>>> > On Sun, 1 Jun 2008, Yinghai Lu wrote:
>>>> >
>>>> >>
>>>> >> make mptable to be consistent to acpi routing, so we could
>>>> >> 1. kexec kernel with acpi=off
>>>> >> 2. workaround BIOS that acpi routing is working, but mptable is not right.
>>>> >> so can use kernel/kexec to start other os that doesn't have good acpi
>> support
>>>> >
>>>> > Is this an effort to boot an ACPI-mode kernel,
>>>> > and then kexec a non-ACPI kernel?
>>>>
>>>> Yes,
>>>
>>> Why is this feature needed?
>>> There are a number of ways that the resulting kernel may fail,
>>> all platform specific.
>>
>> 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.
>
>>>> > 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.
>>
>> 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.
>
>> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 0:49 ` Yinghai Lu
2008-06-19 4:32 ` Eric W. Biederman
@ 2008-06-19 5:20 ` Len Brown
2008-06-19 6:26 ` Yinghai Lu
1 sibling, 1 reply; 65+ messages in thread
From: Len Brown @ 2008-06-19 5:20 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
> >> >> make mptable to be consistent to acpi routing, so we could
> >> >> 1. kexec kernel with acpi=off
> >> >> 2. workaround BIOS that acpi routing is working, but mptable is not right.
> >> >> so can use kernel/kexec to start other os that doesn't have good acpi support
> >> >
> >> > Is this an effort to boot an ACPI-mode kernel,
> >> > and then kexec a non-ACPI kernel?
> >>
> >> Yes,
> >
> > Why is this feature needed?
> > There are a number of ways that the resulting kernel may fail,
> > all platform specific.
>
> 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?
> >> > 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 4:32 ` Eric W. Biederman
2008-06-19 5:09 ` H. Peter Anvin
2008-06-19 5:11 ` Yinghai Lu
@ 2008-06-19 5:27 ` Len Brown
2008-06-19 6:37 ` Eric W. Biederman
2 siblings, 1 reply; 65+ messages in thread
From: Len Brown @ 2008-06-19 5:27 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Yinghai Lu, Ingo Molnar, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, linux-kernel@vger.kernel.org
> >>> > 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.
>
> 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?
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 5:20 ` Len Brown
@ 2008-06-19 6:26 ` Yinghai Lu
2008-06-19 6:28 ` H. Peter Anvin
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 6:26 UTC (permalink / raw)
To: Len Brown
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
On Wed, Jun 18, 2008 at 10:20 PM, Len Brown <lenb@kernel.org> wrote:
>
>
>> >> >> make mptable to be consistent to acpi routing, so we could
>> >> >> 1. kexec kernel with acpi=off
>> >> >> 2. workaround BIOS that acpi routing is working, but mptable is not right.
>> >> >> so can use kernel/kexec to start other os that doesn't have good acpi support
>> >> >
>> >> > Is this an effort to boot an ACPI-mode kernel,
>> >> > and then kexec a non-ACPI kernel?
>> >>
>> >> Yes,
>> >
>> > Why is this feature needed?
>> > There are a number of ways that the resulting kernel may fail,
>> > all platform specific.
>>
>> 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
>
> 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.
>
>> >> > 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.
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.
>
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 6:26 ` Yinghai Lu
@ 2008-06-19 6:28 ` H. Peter Anvin
2008-06-19 6:35 ` Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: H. Peter Anvin @ 2008-06-19 6:28 UTC (permalink / raw)
To: Yinghai Lu
Cc: Len Brown, Ingo Molnar, Thomas Gleixner, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
Yinghai Lu wrote:
>> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 6:28 ` H. Peter Anvin
@ 2008-06-19 6:35 ` Yinghai Lu
0 siblings, 0 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 6:35 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Len Brown, Ingo Molnar, Thomas Gleixner, Andrew Morton,
Eric W. Biederman, linux-kernel@vger.kernel.org
On Wed, Jun 18, 2008 at 11:28 PM, H. Peter Anvin <hpa@zytor.com> wrote:
> Yinghai Lu wrote:
>>>
>>> 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?
1. some other os doesn't support acpi well, and still use mptable.
2. show BIOS engineer how to fix mptable.
YH
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 5:27 ` Len Brown
@ 2008-06-19 6:37 ` Eric W. Biederman
2008-06-19 7:31 ` Yinghai Lu
0 siblings, 1 reply; 65+ messages in thread
From: Eric W. Biederman @ 2008-06-19 6:37 UTC (permalink / raw)
To: Len Brown
Cc: Yinghai Lu, Ingo Molnar, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, linux-kernel@vger.kernel.org
Len Brown <lenb@kernel.org> writes:
>> >>> > 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.
>>
>> 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.
>> 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.
That I will believe.
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: let MPS support selectable
2008-06-19 0:29 ` [PATCH] x86: update mptable fix with no ioapic v2 Yinghai Lu
@ 2008-06-19 7:18 ` Yinghai Lu
2008-06-19 12:13 ` Ingo Molnar
` (2 more replies)
2008-06-19 12:13 ` [PATCH] x86: update mptable fix with no ioapic v2 Ingo Molnar
1 sibling, 3 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 7:18 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Daniel Exner,
Len Brown, linux-kernel@vger.kernel.org
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
arch/x86/Kconfig | 15 ++++++++++++++-
arch/x86/Kconfig.debug | 9 ---------
arch/x86/mm/k8topology_64.c | 4 ++++
3 files changed, 18 insertions(+), 10 deletions(-)
Index: linux-2.6/arch/x86/Kconfig
===================================================================
--- linux-2.6.orig/arch/x86/Kconfig
+++ linux-2.6/arch/x86/Kconfig
@@ -233,6 +233,19 @@ config SMP
If you don't know what to do here, say N.
+config X86_FIND_SMP_CONFIG
+ def_bool y
+ depends on X86_MPPARSE || X86_VOYAGER || X86_VISWS
+ depends on X86_32
+
+config X86_MPPARSE
+ def_bool y
+ bool "Enable MPS table"
+ depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
+ help
+ For old smp systems that do not have proper acpi support. Newer systems
+ (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
+
choice
prompt "Subarchitecture Type"
default X86_PC
@@ -289,7 +302,7 @@ if X86_GENERICARCH
config X86_NUMAQ
bool "NUMAQ (IBM/Sequent)"
- depends on SMP && X86_32 && PCI
+ depends on SMP && X86_32 && PCI && X86_MPPARSE
select NUMA
help
This option is used for getting Linux to run on a NUMAQ (IBM/Sequent)
Index: linux-2.6/arch/x86/Kconfig.debug
===================================================================
--- linux-2.6.orig/arch/x86/Kconfig.debug
+++ linux-2.6/arch/x86/Kconfig.debug
@@ -130,15 +130,6 @@ config 4KSTACKS
on the VM subsystem for higher order allocations. This option
will also use IRQ stacks to compensate for the reduced stackspace.
-config X86_FIND_SMP_CONFIG
- def_bool y
- depends on X86_MPPARSE || X86_VOYAGER || X86_VISWS
- depends on X86_32
-
-config X86_MPPARSE
- def_bool y
- depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
-
config DOUBLEFAULT
default y
bool "Enable doublefault exception handler" if EMBEDDED
Index: linux-2.6/arch/x86/mm/k8topology_64.c
===================================================================
--- linux-2.6.orig/arch/x86/mm/k8topology_64.c
+++ linux-2.6/arch/x86/mm/k8topology_64.c
@@ -57,18 +57,22 @@ static __init void early_get_boot_cpu_id
/*
* Find possible boot-time SMP configuration:
*/
+#ifdef CONFIG_X86_MPPARSE
early_find_smp_config();
+#endif
#ifdef CONFIG_ACPI
/*
* Read APIC information from ACPI tables.
*/
early_acpi_boot_init();
#endif
+#ifdef CONFIG_X86_MPPARSE
/*
* get boot-time SMP configuration:
*/
if (smp_found_config)
early_get_smp_config();
+#endif
early_init_lapic_mapping();
}
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 6:37 ` Eric W. Biederman
@ 2008-06-19 7:31 ` Yinghai Lu
2008-06-19 18:16 ` Len Brown
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 7:31 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Len Brown, Ingo Molnar, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, linux-kernel@vger.kernel.org
On Wed, Jun 18, 2008 at 11:37 PM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
> Len Brown <lenb@kernel.org> writes:
>
>>> >>> > 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.
>>>
>>> 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.
>
>>> 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.
>
> That I will believe.
>
>> 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.
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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable fix with no ioapic v2
2008-06-19 0:29 ` [PATCH] x86: update mptable fix with no ioapic v2 Yinghai Lu
2008-06-19 7:18 ` [PATCH] x86: let MPS support selectable Yinghai Lu
@ 2008-06-19 12:13 ` Ingo Molnar
1 sibling, 0 replies; 65+ messages in thread
From: Ingo Molnar @ 2008-06-19 12:13 UTC (permalink / raw)
To: Yinghai Lu
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Daniel Exner,
Len Brown, linux-kernel@vger.kernel.org
* Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> if the system doesn't have ioapic, we don't need to store entries for
> mptable update
>
> also let mp_config_acpi_gsi not call func in mpparse so later could
> decouple mpparse with acpi more easily
>
> Reported-by: Daniel Exner <dex@dragonslave.de>
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
applied to tip/x86/mpparse - thanks Yinghai.
Ingo
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: let MPS support selectable
2008-06-19 7:18 ` [PATCH] x86: let MPS support selectable Yinghai Lu
@ 2008-06-19 12:13 ` Ingo Molnar
2008-06-19 12:49 ` Ingo Molnar
2008-06-19 15:10 ` Maciej W. Rozycki
[not found] ` <200806191213.10312.yhlu.kernel@gmail.com>
2 siblings, 1 reply; 65+ messages in thread
From: Ingo Molnar @ 2008-06-19 12:13 UTC (permalink / raw)
To: Yinghai Lu
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Daniel Exner,
Len Brown, linux-kernel@vger.kernel.org
applied to tip/x86/mpparse, thanks.
Ingo
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: let MPS support selectable
2008-06-19 12:13 ` Ingo Molnar
@ 2008-06-19 12:49 ` Ingo Molnar
0 siblings, 0 replies; 65+ messages in thread
From: Ingo Molnar @ 2008-06-19 12:49 UTC (permalink / raw)
To: Yinghai Lu
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Daniel Exner,
Len Brown, linux-kernel@vger.kernel.org
* Ingo Molnar <mingo@elte.hu> wrote:
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: let MPS support selectable
2008-06-19 7:18 ` [PATCH] x86: let MPS support selectable Yinghai Lu
2008-06-19 12:13 ` Ingo Molnar
@ 2008-06-19 15:10 ` Maciej W. Rozycki
2008-06-19 17:39 ` Yinghai Lu
[not found] ` <200806191213.10312.yhlu.kernel@gmail.com>
2 siblings, 1 reply; 65+ messages in thread
From: Maciej W. Rozycki @ 2008-06-19 15:10 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Daniel Exner, Len Brown, linux-kernel@vger.kernel.org
On Thu, 19 Jun 2008, Yinghai Lu wrote:
> @@ -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
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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: let MPS support selectable
2008-06-19 15:10 ` Maciej W. Rozycki
@ 2008-06-19 17:39 ` Yinghai Lu
2008-06-19 18:03 ` Len Brown
0 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 17:39 UTC (permalink / raw)
To: Maciej W. Rozycki
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Daniel Exner, Len Brown, linux-kernel@vger.kernel.org
On Thu, Jun 19, 2008 at 8:10 AM, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> On Thu, 19 Jun 2008, Yinghai Lu wrote:
>
>> @@ -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
>
> 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.
thanks. will try to add CONFIG_ACPI_BOOT...
YH
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: let MPS support selectable
2008-06-19 17:39 ` Yinghai Lu
@ 2008-06-19 18:03 ` Len Brown
2008-06-19 18:48 ` Maciej W. Rozycki
0 siblings, 1 reply; 65+ messages in thread
From: Len Brown @ 2008-06-19 18:03 UTC (permalink / raw)
To: Yinghai Lu
Cc: Maciej W. Rozycki, Ingo Molnar, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, Daniel Exner, linux-kernel@vger.kernel.org
On Thu, 19 Jun 2008, Yinghai Lu wrote:
> On Thu, Jun 19, 2008 at 8:10 AM, Maciej W. Rozycki <macro@linux-mips.org> wrote:
> > On Thu, 19 Jun 2008, Yinghai Lu wrote:
> >
> >> @@ -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
> >
> > 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.
>
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 7:31 ` Yinghai Lu
@ 2008-06-19 18:16 ` Len Brown
2008-06-20 6:47 ` Ingo Molnar
0 siblings, 1 reply; 65+ messages in thread
From: Len Brown @ 2008-06-19 18:16 UTC (permalink / raw)
To: Yinghai Lu
Cc: Eric W. Biederman, Ingo Molnar, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, linux-kernel@vger.kernel.org
NAK on this entire direction.
> >>> >>> > 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.
> >>>
> >>> 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.
> >
> >>> 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.
> >
> > That I will believe.
> >
> >> 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.
>
> 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.
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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: let MPS support selectable
2008-06-19 18:03 ` Len Brown
@ 2008-06-19 18:48 ` Maciej W. Rozycki
2008-06-26 9:31 ` Ingo Molnar
0 siblings, 1 reply; 65+ messages in thread
From: Maciej W. Rozycki @ 2008-06-19 18:48 UTC (permalink / raw)
To: Len Brown
Cc: Yinghai Lu, Ingo Molnar, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, Daniel Exner, linux-kernel@vger.kernel.org
On Thu, 19 Jun 2008, Len Brown wrote:
> CONFIG_ACPI_BOOT was removed because it was fundamentally ill-conceived
> and created a situation which was not only more difficult to maintain
> but also didn't work on most machines.
> ACPI interrupt configuration depends on the ACPI interpreter, so to boot
> properly and configure interrupts with ACPI, you need 90% of the kernel's
> ACPI code present anyway.
Fair enough.
> 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.
> 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. :)
> 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.
> However, I think that adding CONFIG_MPS before removing ACPI's
> depencency on mpparse.c has all risk and no value.
Agreed.
Maciej
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: fix compiling when CONFIG_X86_MPPARSE is not set
[not found] ` <200806191213.10312.yhlu.kernel@gmail.com>
@ 2008-06-19 19:15 ` Yinghai Lu
2008-06-20 14:42 ` [PATCH] x86: check command line " Yinghai Lu
[not found] ` <200806200733.31477.yhlu.kernel@gmail.com>
1 sibling, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-19 19:15 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
arch/x86/Kconfig | 2 +-
arch/x86/mm/k8topology_64.c | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
Index: linux-2.6/arch/x86/Kconfig
===================================================================
--- linux-2.6.orig/arch/x86/Kconfig
+++ linux-2.6/arch/x86/Kconfig
@@ -289,7 +289,7 @@ if X86_GENERICARCH
config X86_NUMAQ
bool "NUMAQ (IBM/Sequent)"
- depends on SMP && X86_32 && PCI
+ depends on SMP && X86_32 && PCI && X86_MPPARSE
select NUMA
help
This option is used for getting Linux to run on a NUMAQ (IBM/Sequent)
Index: linux-2.6/arch/x86/mm/k8topology_64.c
===================================================================
--- linux-2.6.orig/arch/x86/mm/k8topology_64.c
+++ linux-2.6/arch/x86/mm/k8topology_64.c
@@ -57,18 +57,22 @@ static __init void early_get_boot_cpu_id
/*
* Find possible boot-time SMP configuration:
*/
+#ifdef CONFIG_X86_MPPARSE
early_find_smp_config();
+#endif
#ifdef CONFIG_ACPI
/*
* Read APIC information from ACPI tables.
*/
early_acpi_boot_init();
#endif
+#ifdef CONFIG_X86_MPPARSE
/*
* get boot-time SMP configuration:
*/
if (smp_found_config)
early_get_smp_config();
+#endif
early_init_lapic_mapping();
}
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-19 18:16 ` Len Brown
@ 2008-06-20 6:47 ` Ingo Molnar
2008-06-20 7:20 ` Yinghai Lu
2008-06-20 9:12 ` Andi Kleen
0 siblings, 2 replies; 65+ messages in thread
From: Ingo Molnar @ 2008-06-20 6:47 UTC (permalink / raw)
To: Len Brown
Cc: Yinghai Lu, Eric W. Biederman, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, linux-kernel@vger.kernel.org
* Len Brown <lenb@kernel.org> wrote:
> > 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.
>
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-20 6:47 ` Ingo Molnar
@ 2008-06-20 7:20 ` Yinghai Lu
2008-06-20 9:12 ` Andi Kleen
1 sibling, 0 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-20 7:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: Len Brown, Eric W. Biederman, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, linux-kernel@vger.kernel.org
On Thu, Jun 19, 2008 at 11:47 PM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Len Brown <lenb@kernel.org> wrote:
>
>> > 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.
>>
>> So you know this can't NEVER be reliable, yet you continue to push for
>> upstream changes that carry risk for all systems that DO work.
>
> Yinghai: Len has a point, could you please double-check that no
> potentially risky code runs by default anywhere, without a specific boot
> option? update_mptable is supposed to achieve that, but lets make sure
> it does its job.
will double check that, and would consider to add
CONFIG_UPDATE_MPTABLE to make it not be built in be default.
YH
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: update mptable v7
2008-06-20 6:47 ` Ingo Molnar
2008-06-20 7:20 ` Yinghai Lu
@ 2008-06-20 9:12 ` Andi Kleen
1 sibling, 0 replies; 65+ messages in thread
From: Andi Kleen @ 2008-06-20 9:12 UTC (permalink / raw)
To: Ingo Molnar
Cc: Len Brown, Yinghai Lu, Eric W. Biederman, Thomas Gleixner,
H. Peter Anvin, Andrew Morton, linux-kernel@vger.kernel.org
Ingo Molnar <mingo@elte.hu> writes:
> Yinghai: Len has a point, could you please double-check that no
> potentially risky code runs by default anywhere, without a specific boot
> option? update_mptable is supposed to achieve that, but lets make sure
> it does its job.
It's not done for the NUMAQ genericarch.
-Andi
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
2008-06-19 19:15 ` [PATCH] x86: fix compiling when CONFIG_X86_MPPARSE is not set Yinghai Lu
@ 2008-06-20 14:42 ` Yinghai Lu
2008-06-20 15:01 ` Ingo Molnar
` (2 more replies)
0 siblings, 3 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-20 14:42 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton
Cc: linux-kernel@vger.kernel.org
we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is
not there
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
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
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -1740,6 +1740,18 @@ static int __init parse_pci(char *arg)
}
early_param("pci", parse_pci);
+void __init acpi_mps_check(void)
+{
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
+/* mptable code is not built-in*/
+ if (acpi_disabled || acpi_noirq) {
+ printk(KERN_ERR "MPS support code is not built-in\n",
+ "so can not use acpi=off or acpi=noirq or pci=noacpi\n");
+ panic("MPS support is not built-in\n");
+ }
+#endif
+}
+
#ifdef CONFIG_X86_IO_APIC
static int __init parse_acpi_skip_timer_override(char *arg)
{
Index: linux-2.6/arch/x86/kernel/setup_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_32.c
+++ linux-2.6/arch/x86/kernel/setup_32.c
@@ -754,6 +754,8 @@ void __init setup_arch(char **cmdline_p)
early_dump_pci_devices();
#endif
+ acpi_mps_check();
+
finish_e820_parsing();
probe_roms();
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -359,6 +359,8 @@ void __init setup_arch(char **cmdline_p)
early_dump_pci_devices();
#endif
+ acpi_mps_check();
+
#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
if (init_ohci1394_dma_early)
init_ohci1394_dma_on_all_controllers();
Index: linux-2.6/include/linux/acpi.h
===================================================================
--- linux-2.6.orig/include/linux/acpi.h
+++ linux-2.6/include/linux/acpi.h
@@ -82,6 +82,7 @@ char * __acpi_map_table (unsigned long p
int early_acpi_boot_init(void);
int acpi_boot_init (void);
int acpi_boot_table_init (void);
+void acpi_mps_check (void);
int acpi_numa_init (void);
int acpi_table_init (void);
@@ -250,6 +251,10 @@ static inline int acpi_boot_table_init(v
return 0;
}
+static inline void acpi_mps_check(void)
+{
+}
+
static inline int acpi_check_resource_conflict(struct resource *res)
{
return 0;
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
2008-06-20 14:42 ` [PATCH] x86: check command line " Yinghai Lu
@ 2008-06-20 15:01 ` Ingo Molnar
2008-06-20 15:04 ` Yinghai Lu
2008-06-20 15:36 ` Maciej W. Rozycki
2008-06-20 23:11 ` [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set v2 Yinghai Lu
2008-06-24 12:12 ` [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set Pavel Machek
2 siblings, 2 replies; 65+ messages in thread
From: Ingo Molnar @ 2008-06-20 15:01 UTC (permalink / raw)
To: Yinghai Lu
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton,
linux-kernel@vger.kernel.org
* Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: simplify x86_mpparse dependency check
[not found] ` <200806200733.31477.yhlu.kernel@gmail.com>
@ 2008-06-20 15:03 ` Ingo Molnar
2008-06-20 15:31 ` Maciej W. Rozycki
1 sibling, 0 replies; 65+ messages in thread
From: Ingo Molnar @ 2008-06-20 15:03 UTC (permalink / raw)
To: Yinghai Lu
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton, Maciej W. Rozycki,
Len Brown, linux-kernel@vger.kernel.org
* Yinghai Lu <yhlu.kernel@gmail.com> wrote:
> [PATCH] x86: simplify x86_mpparse dependency check
>
> "Maciej W. Rozycki" <macro@linux-mips.org> said:
>
> > 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.
>
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
applied to tip/x86/mpparse - thanks Yinghai.
Ingo
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
2008-06-20 15:01 ` Ingo Molnar
@ 2008-06-20 15:04 ` Yinghai Lu
2008-06-20 15:36 ` Maciej W. Rozycki
1 sibling, 0 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-20 15:04 UTC (permalink / raw)
To: Ingo Molnar
Cc: Thomas Gleixner, H. Peter Anvin, Andrew Morton,
linux-kernel@vger.kernel.org
On Fri, Jun 20, 2008 at 8:01 AM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Yinghai Lu <yhlu.kernel@gmail.com> wrote:
>
>> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: simplify x86_mpparse dependency check
[not found] ` <200806200733.31477.yhlu.kernel@gmail.com>
2008-06-20 15:03 ` [PATCH] x86: simplify x86_mpparse dependency check Ingo Molnar
@ 2008-06-20 15:31 ` Maciej W. Rozycki
1 sibling, 0 replies; 65+ messages in thread
From: Maciej W. Rozycki @ 2008-06-20 15:31 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Len Brown, linux-kernel@vger.kernel.org
On Fri, 20 Jun 2008, Yinghai Lu wrote:
> [PATCH] x86: simplify x86_mpparse dependency check
Thanks for this clean-up.
Maciej
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
2008-06-20 15:01 ` Ingo Molnar
2008-06-20 15:04 ` Yinghai Lu
@ 2008-06-20 15:36 ` Maciej W. Rozycki
1 sibling, 0 replies; 65+ messages in thread
From: Maciej W. Rozycki @ 2008-06-20 15:36 UTC (permalink / raw)
To: Ingo Molnar
Cc: Yinghai Lu, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
linux-kernel@vger.kernel.org
On Fri, 20 Jun 2008, Ingo Molnar wrote:
> 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
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set v2
2008-06-20 14:42 ` [PATCH] x86: check command line " Yinghai Lu
2008-06-20 15:01 ` Ingo Molnar
@ 2008-06-20 23:11 ` Yinghai Lu
2008-06-21 8:14 ` [PATCH] x86: clean up init_amd() Yinghai Lu
2008-06-24 12:12 ` [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set Pavel Machek
2 siblings, 1 reply; 65+ messages in thread
From: Yinghai Lu @ 2008-06-20 23:11 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
Maciej W. Rozycki
Cc: linux-kernel@vger.kernel.org
if acpi=off, acpi=noirq and pci=noacpi, we need to disable apic
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
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(-)
Index: linux-2.6/arch/x86/kernel/acpi/boot.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
+++ linux-2.6/arch/x86/kernel/acpi/boot.c
@@ -1740,6 +1740,20 @@ static int __init parse_pci(char *arg)
}
early_param("pci", parse_pci);
+int __init acpi_mps_check(void)
+{
+#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
+/* mptable code is not built-in*/
+ if (acpi_disabled || acpi_noirq) {
+ printk(KERN_WARNING "MPS support code is not built-in.\n"
+ "Using acpi=off or acpi=noirq or pci=noacpi "
+ "may have problem\n");
+ return 1;
+ }
+#endif
+ return 0;
+}
+
#ifdef CONFIG_X86_IO_APIC
static int __init parse_acpi_skip_timer_override(char *arg)
{
Index: linux-2.6/arch/x86/kernel/setup_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_32.c
+++ linux-2.6/arch/x86/kernel/setup_32.c
@@ -689,6 +689,11 @@ void __init setup_arch(char **cmdline_p)
early_dump_pci_devices();
#endif
+ if (acpi_mps_check()){
+ enable_local_apic = -1;
+ clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+ }
+
finish_e820_parsing();
probe_roms();
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -319,6 +319,11 @@ void __init setup_arch(char **cmdline_p)
early_dump_pci_devices();
#endif
+ if (acpi_mps_check()) {
+ disable_apic = 1;
+ clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
+ }
+
#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
if (init_ohci1394_dma_early)
init_ohci1394_dma_on_all_controllers();
@@ -740,6 +745,10 @@ static void __cpuinit early_identify_cpu
cpu_devs[c->x86_vendor]->c_early_init(c);
validate_pat_support(c);
+
+ /* early_param could clear that, but recall get it set again */
+ if (disable_apic)
+ clear_cpu_cap(c, X86_FEATURE_APIC);
}
/*
Index: linux-2.6/include/linux/acpi.h
===================================================================
--- linux-2.6.orig/include/linux/acpi.h
+++ linux-2.6/include/linux/acpi.h
@@ -82,6 +82,7 @@ char * __acpi_map_table (unsigned long p
int early_acpi_boot_init(void);
int acpi_boot_init (void);
int acpi_boot_table_init (void);
+int acpi_mps_check (void);
int acpi_numa_init (void);
int acpi_table_init (void);
@@ -250,6 +251,11 @@ static inline int acpi_boot_table_init(v
return 0;
}
+static inline int acpi_mps_check(void)
+{
+ return 0;
+}
+
static inline int acpi_check_resource_conflict(struct resource *res)
{
return 0;
Index: linux-2.6/arch/x86/kernel/setup.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup.c
+++ linux-2.6/arch/x86/kernel/setup.c
@@ -161,6 +161,10 @@ void __init setup_per_cpu_areas(void)
char *ptr;
int cpu;
+ /* no processor from mptable or madt */
+ if (!num_processors)
+ num_processors = 1;
+
#ifdef CONFIG_HOTPLUG_CPU
prefill_possible_map();
#else
Index: linux-2.6/arch/x86/kernel/apic_32.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/apic_32.c
+++ linux-2.6/arch/x86/kernel/apic_32.c
@@ -57,7 +57,7 @@ unsigned long mp_lapic_addr;
*
* -1=force-disable, +1=force-enable
*/
-static int enable_local_apic __initdata;
+int enable_local_apic;
/* Local APIC timer verification ok */
static int local_apic_timer_verify_ok;
Index: linux-2.6/include/asm-x86/apic.h
===================================================================
--- linux-2.6.orig/include/asm-x86/apic.h
+++ linux-2.6/include/asm-x86/apic.h
@@ -39,8 +39,12 @@ extern int apic_verbosity;
extern int local_apic_timer_c2_ok;
extern int ioapic_force;
-extern int disable_apic;
+#ifdef CONFIG_X86_64
+extern int disable_apic;
+#else
+extern int enable_local_apic;
+#endif
/*
* Basic functions accessing APICs.
*/
^ permalink raw reply [flat|nested] 65+ messages in thread
* [PATCH] x86: clean up init_amd()
2008-06-20 23:11 ` [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set v2 Yinghai Lu
@ 2008-06-21 8:14 ` Yinghai Lu
0 siblings, 0 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-21 8:14 UTC (permalink / raw)
To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin; +Cc: linux-kernel@vger.kernel.org
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
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
---
arch/x86/kernel/cpu/amd_64.c | 22 ++++++++++++++--------
arch/x86/kernel/setup_64.c | 4 ----
2 files changed, 14 insertions(+), 12 deletions(-)
Index: linux-2.6/arch/x86/kernel/cpu/amd_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/amd_64.c
+++ linux-2.6/arch/x86/kernel/cpu/amd_64.c
@@ -131,7 +131,7 @@ static void __cpuinit init_amd(struct cp
* Errata 63 for SH-B3 steppings
* Errata 122 for all steppings (F+ have it disabled by default)
*/
- if (c->x86 == 15) {
+ if (c->x86 == 0xf) {
rdmsrl(MSR_K8_HWCR, value);
value |= 1 << 6;
wrmsrl(MSR_K8_HWCR, value);
@@ -143,10 +143,11 @@ static void __cpuinit init_amd(struct cp
clear_cpu_cap(c, 0*32+31);
/* On C+ stepping K8 rep microcode works well for copy/memset */
- level = cpuid_eax(1);
- if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) ||
- level >= 0x0f58))
- set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+ if (c->x86 == 0xf) {
+ level = cpuid_eax(1);
+ if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
+ set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+ }
if (c->x86 == 0x10 || c->x86 == 0x11)
set_cpu_cap(c, X86_FEATURE_REP_GOOD);
@@ -157,7 +158,7 @@ static void __cpuinit init_amd(struct cp
level = get_model_name(c);
if (!level) {
switch (c->x86) {
- case 15:
+ case 0xf:
/* Should distinguish Models here, but this is only
a fallback anyways. */
strcpy(c->x86_model_id, "Hammer");
@@ -176,14 +177,19 @@ static void __cpuinit init_amd(struct cp
else
num_cache_leaves = 3;
- if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11)
+ if (c->x86 >= 0xf && c->x86 <= 0x11)
set_cpu_cap(c, X86_FEATURE_K8);
/* MFENCE stops RDTSC speculation */
set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
- if (c->x86 == 0x10)
+ if (c->x86 == 0x10) {
+ /* do this for boot cpu */
+ if (c == &boot_cpu_data)
+ check_enable_amd_mmconf_dmi();
+
fam10h_check_enable_mmcfg();
+ }
if (c == &boot_cpu_data && c->x86 >= 0xf && c->x86 <= 0x11) {
unsigned long long tseg;
Index: linux-2.6/arch/x86/kernel/setup_64.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/setup_64.c
+++ linux-2.6/arch/x86/kernel/setup_64.c
@@ -72,7 +72,6 @@
#include <asm/topology.h>
#include <asm/trampoline.h>
#include <asm/pat.h>
-#include <asm/mmconfig.h>
#include <mach_apic.h>
#ifdef CONFIG_PARAVIRT
@@ -491,9 +490,6 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con;
#endif
#endif
-
- /* do this before identify_cpu for boot cpu */
- check_enable_amd_mmconf_dmi();
}
struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {};
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
2008-06-20 14:42 ` [PATCH] x86: check command line " Yinghai Lu
2008-06-20 15:01 ` Ingo Molnar
2008-06-20 23:11 ` [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set v2 Yinghai Lu
@ 2008-06-24 12:12 ` Pavel Machek
2008-06-26 8:23 ` Yinghai Lu
2 siblings, 1 reply; 65+ messages in thread
From: Pavel Machek @ 2008-06-24 12:12 UTC (permalink / raw)
To: Yinghai Lu
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
linux-kernel@vger.kernel.org
Hi!
> we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is
> not there
>
> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
>
> ---
> 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
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
> +++ linux-2.6/arch/x86/kernel/acpi/boot.c
> @@ -1740,6 +1740,18 @@ static int __init parse_pci(char *arg)
> }
> early_param("pci", parse_pci);
>
> +void __init acpi_mps_check(void)
> +{
> +#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
> +/* mptable code is not built-in*/
> + if (acpi_disabled || acpi_noirq) {
> + printk(KERN_ERR "MPS support code is not built-in\n",
> + "so can not use acpi=off or acpi=noirq or pci=noacpi\n");
> + panic("MPS support is not built-in\n");
> + }
> +#endif
I'd say this is good enough reason not to make X86_MPPARSE optional.
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set
2008-06-24 12:12 ` [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set Pavel Machek
@ 2008-06-26 8:23 ` Yinghai Lu
0 siblings, 0 replies; 65+ messages in thread
From: Yinghai Lu @ 2008-06-26 8:23 UTC (permalink / raw)
To: Pavel Machek
Cc: Ingo Molnar, Thomas Gleixner, H. Peter Anvin, Andrew Morton,
linux-kernel@vger.kernel.org
On Tue, Jun 24, 2008 at 5:12 AM, Pavel Machek <pavel@suse.cz> wrote:
> Hi!
>
>> we can not use acpi=off, acpi=noirq and pci=noacpi when mps support is
>> not there
>>
>> Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
>>
>> ---
>> 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
>> ===================================================================
>> --- linux-2.6.orig/arch/x86/kernel/acpi/boot.c
>> +++ linux-2.6/arch/x86/kernel/acpi/boot.c
>> @@ -1740,6 +1740,18 @@ static int __init parse_pci(char *arg)
>> }
>> early_param("pci", parse_pci);
>>
>> +void __init acpi_mps_check(void)
>> +{
>> +#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
>> +/* mptable code is not built-in*/
>> + if (acpi_disabled || acpi_noirq) {
>> + printk(KERN_ERR "MPS support code is not built-in\n",
>> + "so can not use acpi=off or acpi=noirq or pci=noacpi\n");
>> + panic("MPS support is not built-in\n");
>> + }
>> +#endif
>
> I'd say this is good enough reason not to make X86_MPPARSE optional.
>
new patch in tip/master, it will disable smp instead of panic.
YH
^ permalink raw reply [flat|nested] 65+ messages in thread
* Re: [PATCH] x86: let MPS support selectable
2008-06-19 18:48 ` Maciej W. Rozycki
@ 2008-06-26 9:31 ` Ingo Molnar
0 siblings, 0 replies; 65+ messages in thread
From: Ingo Molnar @ 2008-06-26 9:31 UTC (permalink / raw)
To: Maciej W. Rozycki
Cc: Len Brown, Yinghai Lu, Thomas Gleixner, H. Peter Anvin,
Andrew Morton, Daniel Exner, linux-kernel@vger.kernel.org
* Maciej W. Rozycki <macro@linux-mips.org> wrote:
> > However, I think that adding CONFIG_MPS before removing ACPI's
> > depencency on mpparse.c has all risk and no value.
>
> Agreed.
that should be sorted out mostly in -tip/x86, Alexey Starikovskiy went
through a marathon session decoupling them, about two months ago:
$ git-shortlog --stat --author=astarikovskiy linus/master..tip/master
Alexey Starikovskiy (12):
x86: move es7000_plat out of mpparse.c
x86: complete move ACPI from mpparse.c
x86: make mp_ioapic_routing definition local
x86: make struct config_ioapic not MPspec specific
x86: make config_irqsrc not MPspec specific
x86: fix mpparse/acpi interaction
x86: Set pic_mode only if local apic code is present
x86: move pic_mode to apic_32.c
x86: move smp_found_config
x86: mp_bus_id_to_pci_bus is not needed
x86: move mp_bus_not_pci from mpparse.c
x86: allow MPPARSE to be deselected in SMP configs
22 files changed, 524 insertions(+), 501 deletions(-)
it's all in linux-next as well.
Ingo
^ permalink raw reply [flat|nested] 65+ messages in thread
end of thread, other threads:[~2008-06-26 9:31 UTC | newest]
Thread overview: 65+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <200805041823.57198.yhlu.kernel@gmail.com>
2008-05-06 17:38 ` [PATCH] x86: update mptable Yinghai Lu
2008-05-06 17:41 ` [PATCH] x86: fixed mtrr change WP to WB Yinghai Lu
2008-05-06 17:48 ` H. Peter Anvin
2008-05-06 18:24 ` Yinghai Lu
2008-05-06 18:31 ` H. Peter Anvin
2008-05-06 18:34 ` Yinghai Lu
2008-05-06 18:43 ` H. Peter Anvin
2008-05-06 19:05 ` Yinghai Lu
2008-05-06 19:08 ` H. Peter Anvin
2008-05-06 19:15 ` Yinghai Lu
2008-05-07 7:48 ` [PATCH] x86: update mptable v2 Yinghai Lu
2008-05-17 2:32 ` [PATCH] x86: update mptable v3 Yinghai Lu
2008-05-19 15:46 ` Ingo Molnar
2008-05-19 19:35 ` [PATCH] x86: update mptable v4 Yinghai Lu
2008-05-19 19:52 ` [PATCH] x86: update mptable v5 Yinghai Lu
2008-05-25 23:00 ` [PATCH] x86: update mptable v6 Yinghai Lu
2008-06-01 20:17 ` [PATCH] x86: update mptable v7 Yinghai Lu
2008-06-09 2:53 ` [PATCH] x86: update mptable v7 - fix Yinghai Lu
2008-06-09 10:13 ` Ingo Molnar
2008-06-09 17:51 ` Yinghai Lu
2008-06-09 18:11 ` Maciej W. Rozycki
2008-06-09 19:09 ` Ingo Molnar
2008-06-09 19:38 ` Yinghai Lu
2008-06-09 19:46 ` H. Peter Anvin
2008-06-09 19:49 ` Maciej W. Rozycki
2008-06-18 21:32 ` [PATCH] x86: update mptable fix with no ioapic Yinghai Lu
2008-06-19 0:29 ` [PATCH] x86: update mptable fix with no ioapic v2 Yinghai Lu
2008-06-19 7:18 ` [PATCH] x86: let MPS support selectable Yinghai Lu
2008-06-19 12:13 ` Ingo Molnar
2008-06-19 12:49 ` Ingo Molnar
2008-06-19 15:10 ` Maciej W. Rozycki
2008-06-19 17:39 ` Yinghai Lu
2008-06-19 18:03 ` Len Brown
2008-06-19 18:48 ` Maciej W. Rozycki
2008-06-26 9:31 ` Ingo Molnar
[not found] ` <200806191213.10312.yhlu.kernel@gmail.com>
2008-06-19 19:15 ` [PATCH] x86: fix compiling when CONFIG_X86_MPPARSE is not set Yinghai Lu
2008-06-20 14:42 ` [PATCH] x86: check command line " Yinghai Lu
2008-06-20 15:01 ` Ingo Molnar
2008-06-20 15:04 ` Yinghai Lu
2008-06-20 15:36 ` Maciej W. Rozycki
2008-06-20 23:11 ` [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set v2 Yinghai Lu
2008-06-21 8:14 ` [PATCH] x86: clean up init_amd() Yinghai Lu
2008-06-24 12:12 ` [PATCH] x86: check command line when CONFIG_X86_MPPARSE is not set Pavel Machek
2008-06-26 8:23 ` Yinghai Lu
[not found] ` <200806200733.31477.yhlu.kernel@gmail.com>
2008-06-20 15:03 ` [PATCH] x86: simplify x86_mpparse dependency check Ingo Molnar
2008-06-20 15:31 ` Maciej W. Rozycki
2008-06-19 12:13 ` [PATCH] x86: update mptable fix with no ioapic v2 Ingo Molnar
2008-06-18 22:18 ` [PATCH] x86: update mptable v7 Len Brown
2008-06-18 22:32 ` Yinghai Lu
2008-06-19 0:33 ` Len Brown
2008-06-19 0:49 ` Yinghai Lu
2008-06-19 4:32 ` Eric W. Biederman
2008-06-19 5:09 ` H. Peter Anvin
2008-06-19 5:11 ` Yinghai Lu
2008-06-19 5:27 ` Len Brown
2008-06-19 6:37 ` Eric W. Biederman
2008-06-19 7:31 ` Yinghai Lu
2008-06-19 18:16 ` Len Brown
2008-06-20 6:47 ` Ingo Molnar
2008-06-20 7:20 ` Yinghai Lu
2008-06-20 9:12 ` Andi Kleen
2008-06-19 5:20 ` Len Brown
2008-06-19 6:26 ` Yinghai Lu
2008-06-19 6:28 ` H. Peter Anvin
2008-06-19 6:35 ` Yinghai Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox