Patchwork make I/O APIC IDs and processor APIC IDs unique (asus/m4a785-m)

login
register
about
Submitter Scott
Date 2010-09-15 03:42:08
Message ID <84EE4926AB0F408B9D609983F6BFCEE4@m3a78>
Download mbox | patch
Permalink /patch/1944/
State New
Headers show

Comments

Scott - 2010-09-15 03:42:08
For the AMD SB700 projects, the SB ioapic id is being assigned the same
value as one of the processor core local apic ids. Apparently this is not
such a serious problem as I had once thought. On the other hand, AMD
recommends using a unique value for each apic id.

Assigning a unique id to the SB ioapic is not as simple as choosing the
next biggest available value, because the ioapic is traditionally a 4-bit
value. Though the south bridge has an option for an 8-bit ioapic id,
using such a value might confuse older operating systems. Choosing the
next available id value for the ioapic works when the number of processor
cores is small, and that is what the AMD BKDG recommends. If this would
result in an ioapic id that exceeds 4 bits, the recommendation is to lift
the processor local apic id numbering so that ioapics can be assigned
values starting at zero. The patch below attempts to implement these
recommendations. The case of lifting local apic ids has not been tested.
In order to meet the 4-bit ioapic id limit without lifting the processor
local apic id values, the patch reduces MAX_PHYSICAL_CPUS from 2 to 1,
which is consistent with the currently supported boards and processors.
The patch is for asus/m4a785-m, but can be adapted for other supported
sb700 desktop projects. Tested by booting amd/m4a785-m/seabios to win7
on simnow. The initial and final ioapic id, as well as the value in the
acpi apic table, are 8.

Signed-off-by: Scott Duplichan <scott@notabs.org>
Peter Stuge - 2010-09-15 10:53:24
Scott Duplichan wrote:
> Assigning a unique id to the SB ioapic is not as simple as choosing
> the next biggest available value, because the ioapic is
> traditionally a 4-bit value.

Did you look at how the K8 support does this? I think this may
already be handled there, maybe it's a useful reference.


> +++ src/southbridge/amd/sb700/sb700_sm.c	(working copy)
> +   #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16)
..

> +++ src/mainboard/asus/m4a785-m/acpi_tables.c	(working copy)
> +   #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16)
> +   #define IO_APIC_ID (CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS)
> +   #else
> +   #define IO_APIC_ID 0
> +   #endif

Is there a header file in north or southbridge that could be used to
store the logic?


//Peter
Marc Jones - 2010-09-15 17:36:25
On Wed, Sep 15, 2010 at 4:53 AM, Peter Stuge <peter@stuge.se> wrote:
> Scott Duplichan wrote:
>> Assigning a unique id to the SB ioapic is not as simple as choosing
>> the next biggest available value, because the ioapic is
>> traditionally a 4-bit value.
>
> Did you look at how the K8 support does this? I think this may
> already be handled there, maybe it's a useful reference.
>

K8 and Fa10 have the same option to lift the BSP APIC ID, The code
looks stale and I don't think that it would be enough for FAM10. For
K8 you only need to move one ID to make room for the SB (2*8). For
FAM10, you need to lift more than just the BSP.


>
>> +++ src/southbridge/amd/sb700/sb700_sm.c      (working copy)
>> +   #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16)
> ..

Have you tried setting CONFIG_APIC_ID_OFFSET?

>
>> +++ src/mainboard/asus/m4a785-m/acpi_tables.c (working copy)
>> +   #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16)
>> +   #define IO_APIC_ID (CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS)
>> +   #else
>> +   #define IO_APIC_ID 0
>> +   #endif
>
> Is there a header file in north or southbridge that could be used to
> store the logic?

I agree, this doesn't belong in acpi code.  IO_APIC_ID could be used
in the sb700_sm.c as well.

Marc
Scott - 2010-09-15 18:00:47
]-----Original Message-----
]From: coreboot-bounces@coreboot.org [mailto:coreboot-bounces@coreboot.org] On Behalf Of Marc Jones
]Sent: Wednesday, September 15, 2010 12:36 PM
]To: coreboot@coreboot.org
]Subject: Re: [coreboot] [PATCH] make I/O APIC IDs and processor APIC IDs unique (asus/m4a785-m)
]
]On Wed, Sep 15, 2010 at 4:53 AM, Peter Stuge <peter@stuge.se> wrote:
]> Scott Duplichan wrote:
]>> Assigning a unique id to the SB ioapic is not as simple as choosing
]>> the next biggest available value, because the ioapic is
]>> traditionally a 4-bit value.
]>
]> Did you look at how the K8 support does this? I think this may
]> already be handled there, maybe it's a useful reference.
]>
]
]K8 and Fa10 have the same option to lift the BSP APIC ID, The code
]looks stale and I don't think that it would be enough for FAM10. For
]K8 you only need to move one ID to make room for the SB (2*8). For
]FAM10, you need to lift more than just the BSP.
]
]
]>
]>> +++ src/southbridge/amd/sb700/sb700_sm.c      (working copy)
]>> +   #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16)
]> ..
]
]Have you tried setting CONFIG_APIC_ID_OFFSET?

I didn't even test this method because AMD recommends starting the processor
local apic ids at zero if possible. That is for better compatibility with
some older operating systems I believe. I think none of the coreboot AMD
projects currently support >= 16 cores, so processor apic IDs can start at
zero for the time being. But even if this lifting method resolves the ID
conflict, it does not solve the problem of passing the io apic id to the
os through acpi. Currently the acpi tables use a hard-coded value of 2 for
the io apic id. So there are two problems: ID conflict, and ACPI reporting.

]>
]>> +++ src/mainboard/asus/m4a785-m/acpi_tables.c (working copy)
]>> +   #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16)
]>> +   #define IO_APIC_ID (CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS)
]>> +   #else
]>> +   #define IO_APIC_ID 0
]>> +   #endif
]>
]> Is there a header file in north or southbridge that could be used to
]> store the logic?
]
]I agree, this doesn't belong in acpi code.  IO_APIC_ID could be used
]in the sb700_sm.c as well.

It seems like a generic sysconf structure is needed. sb700_sm.c could
use such a structure to pass the io apic id base to acpi_tables.c.

]Marc
]
]-- 
]http://se-eng.com

Patch

Index: src/southbridge/amd/sb700/sb700_sm.c
===================================================================
--- src/southbridge/amd/sb700/sb700_sm.c	(revision 5814)
+++ src/southbridge/amd/sb700/sb700_sm.c	(working copy)
@@ -57,12 +57,20 @@ 
 	printk(BIOS_INFO, "sm_init().\n");
 
 	ioapic_base = pci_read_config32(dev, 0x74) & (0xffffffe0);	/* some like mem resource, but does not have  enable bit */
-	/* Don't rename APIC ID */
-	/* TODO: We should call setup_ioapic() here. But kernel hangs if cpu is K8.
-	 * We need to check out why and change back. */
+	
 	clear_ioapic(ioapic_base);
+   /* I/O APIC IDs are normally limited to 4-bits. Enforce this limit. */
+   #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16)
+	/* Assign the ioapic ID the next available number after the processor core local APIC IDs */
+	setup_ioapic(ioapic_base, CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS);
+   #elif (CONFIG_APIC_ID_OFFSET > 0)
+   /* Assign the ioapic ID the value 0. Processor APIC IDs follow. */ 
+	setup_ioapic(ioapic_base, 0);
+   #else
+   #error "The processor APIC IDs must be lifted to make room for the I/O APIC ID"
+   #endif
 
-	/* 2.10 Interrupt Routing/Filtering */
+ 	/* 2.10 Interrupt Routing/Filtering */
 	dword = pci_read_config8(dev, 0x62);
 	dword |= 3;
 	pci_write_config8(dev, 0x62, dword);
Index: src/mainboard/asus/m4a785-m/Kconfig
===================================================================
--- src/mainboard/asus/m4a785-m/Kconfig	(revision 5814)
+++ src/mainboard/asus/m4a785-m/Kconfig	(working copy)
@@ -49,7 +49,7 @@ 
 
 config MAX_PHYSICAL_CPUS
 	int
-	default 2
+	default 1
 
 config HW_MEM_HOLE_SIZE_AUTO_INC
 	bool
Index: src/mainboard/asus/m4a785-m/acpi_tables.c
===================================================================
--- src/mainboard/asus/m4a785-m/acpi_tables.c	(revision 5814)
+++ src/mainboard/asus/m4a785-m/acpi_tables.c	(working copy)
@@ -70,7 +70,13 @@ 
 	current = acpi_create_madt_lapics(current);
 
 	/* Write SB700 IOAPIC, only one */
-	current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, 2,
+   #if (CONFIG_APIC_ID_OFFSET == 0 && CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS < 16)
+   #define IO_APIC_ID (CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS)
+   #else
+   #define IO_APIC_ID 0
+   #endif
+	current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
+					   IO_APIC_ID,
 					   IO_APIC_ADDR, 0);
 
 	current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)