2005-04-17 02:20:36 +04:00
/*
* Copyright 2004 James Cleverdon , IBM .
* Subject to the GNU Public License , v .2
*
* Generic APIC sub - arch probe layer .
*
* Hacked for x86 - 64 by James Cleverdon from i386 architecture code by
* Martin Bligh , Andi Kleen , James Bottomley , John Stultz , and
* James Cleverdon .
*/
# include <linux/threads.h>
# include <linux/cpumask.h>
# include <linux/string.h>
2007-05-02 21:27:04 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/kernel.h>
# include <linux/ctype.h>
# include <linux/init.h>
2008-03-28 22:12:16 +03:00
# include <linux/hardirq.h>
2005-04-17 02:20:36 +04:00
# include <asm/smp.h>
# include <asm/ipi.h>
2007-05-02 21:27:04 +04:00
# include <asm/genapic.h>
2005-04-17 02:20:36 +04:00
2007-05-02 21:27:04 +04:00
# ifdef CONFIG_ACPI
2005-04-17 02:24:53 +04:00
# include <acpi/acpi_bus.h>
# endif
2008-03-28 22:12:16 +03:00
DEFINE_PER_CPU ( int , x2apic_extra_bits ) ;
2005-04-17 02:20:36 +04:00
2007-05-02 21:27:04 +04:00
struct genapic __read_mostly * genapic = & apic_flat ;
2005-04-17 02:20:36 +04:00
2008-03-28 22:12:06 +03:00
static enum uv_system_type uv_system_type ;
2005-04-17 02:20:36 +04:00
/*
* Check the APIC IDs in bios_cpu_apicid and choose the APIC mode .
*/
2007-05-02 21:27:04 +04:00
void __init setup_apic_routing ( void )
2005-04-17 02:20:36 +04:00
{
2008-03-28 22:12:16 +03:00
if ( uv_system_type = = UV_NON_UNIQUE_APIC )
genapic = & apic_x2apic_uv_x ;
else
2007-05-02 21:27:04 +04:00
# ifdef CONFIG_ACPI
2005-04-17 02:24:53 +04:00
/*
2007-05-02 21:27:04 +04:00
* Quirk : some x86_64 machines can only use physical APIC mode
* regardless of how many processors are present ( x86_64 ES7000
* is an example ) .
2005-04-17 02:24:53 +04:00
*/
2007-05-02 21:27:04 +04:00
if ( acpi_gbl_FADT . header . revision > FADT2_REVISION_ID & &
( acpi_gbl_FADT . flags & ACPI_FADT_APIC_PHYSICAL ) )
genapic = & apic_physflat ;
2007-05-02 21:27:04 +04:00
else
2005-04-17 02:24:53 +04:00
# endif
2008-04-19 18:55:17 +04:00
if ( num_possible_cpus ( ) < = 8 )
2005-04-17 02:20:36 +04:00
genapic = & apic_flat ;
2007-05-02 21:27:04 +04:00
else
2007-05-02 21:27:04 +04:00
genapic = & apic_physflat ;
2005-04-17 02:20:36 +04:00
printk ( KERN_INFO " Setting APIC routing to %s \n " , genapic - > name ) ;
}
2007-05-02 21:27:04 +04:00
/* Same for both flat and physical. */
2005-04-17 02:20:36 +04:00
void send_IPI_self ( int vector )
{
__send_IPI_shortcut ( APIC_DEST_SELF , vector , APIC_DEST_PHYSICAL ) ;
}
2008-03-28 22:12:06 +03:00
int __init acpi_madt_oem_check ( char * oem_id , char * oem_table_id )
{
if ( ! strcmp ( oem_id , " SGI " ) ) {
if ( ! strcmp ( oem_table_id , " UVL " ) )
uv_system_type = UV_LEGACY_APIC ;
else if ( ! strcmp ( oem_table_id , " UVX " ) )
uv_system_type = UV_X2APIC ;
else if ( ! strcmp ( oem_table_id , " UVH " ) )
uv_system_type = UV_NON_UNIQUE_APIC ;
}
return 0 ;
}
2008-03-28 22:12:16 +03:00
unsigned int read_apic_id ( void )
{
unsigned int id ;
WARN_ON ( preemptible ( ) ) ;
id = apic_read ( APIC_ID ) ;
if ( uv_system_type > = UV_X2APIC )
id | = __get_cpu_var ( x2apic_extra_bits ) ;
return id ;
}
2008-03-28 22:12:06 +03:00
enum uv_system_type get_uv_system_type ( void )
{
return uv_system_type ;
}
int is_uv_system ( void )
{
return uv_system_type ! = UV_NONE ;
}