[PATCH] i386: Consolidate modern APIC handling

AMD systems have a modern APIC that supports 8 bit IDs, but
don't have a XAPIC version number.  Add a new "modern_apic"
subfunction that handles this correctly and use it (nearly)
everywhere where XAPIC is tested for.

I removed one wart: the code specified that external APICs
would use an 8bit APIC ID. But I checked a real 82093 data sheet
and it says clearly that they only use 4bit. So I removed
this special case since it would a bit awkward to implement now.

I removed the valid APIC tests in mptable parsing completely. On any modern
system they only check against the full field width (8bit) anyways
and are no-ops. This also fixes them doing the wrong thing
on >8 core Opterons.

This makes i386 boot again on 16 core Opterons.

Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Andi Kleen 2006-04-07 19:49:45 +02:00 committed by Linus Torvalds
parent d1530d82e0
commit 95d769aaf4
3 changed files with 18 additions and 28 deletions

View file

@ -62,6 +62,18 @@ int apic_verbosity;
static void apic_pm_activate(void);
int modern_apic(void)
{
unsigned int lvr, version;
/* AMD systems use old APIC versions, so check the CPU */
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
boot_cpu_data.x86 >= 0xf)
return 1;
lvr = apic_read(APIC_LVR);
version = GET_APIC_VERSION(lvr);
return version >= 0x14;
}
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves.
@ -119,10 +131,7 @@ void enable_NMI_through_LVT0 (void * dummy)
int get_physical_broadcast(void)
{
unsigned int lvr, version;
lvr = apic_read(APIC_LVR);
version = GET_APIC_VERSION(lvr);
if (!APIC_INTEGRATED(version) || version >= 0x14)
if (modern_apic())
return 0xff;
else
return 0xf;
@ -349,9 +358,9 @@ int __init verify_local_APIC(void)
void __init sync_Arb_IDs(void)
{
/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
if (ver >= 0x14) /* P4 or higher */
/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
And not needed on AMD */
if (modern_apic())
return;
/*
* Wait for idle.

View file

@ -110,21 +110,6 @@ static int __init mpf_checksum(unsigned char *mp, int len)
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
#ifdef CONFIG_X86_NUMAQ
static int MP_valid_apicid(int apicid, int version)
{
return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
}
#else
static int MP_valid_apicid(int apicid, int version)
{
if (version >= 0x14)
return apicid < 0xff;
else
return apicid < 0xf;
}
#endif
static void __devinit MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
@ -190,12 +175,6 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
ver = m->mpc_apicver;
if (!MP_valid_apicid(apicid, ver)) {
printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
m->mpc_apicid, MAX_APICS);
return;
}
/*
* Validate version
*/

View file

@ -139,6 +139,8 @@ void switch_ipi_to_APIC_timer(void *cpumask);
extern int timer_over_8254;
extern int modern_apic(void);
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }