x86: make apic_32/64.c more like
except x2apic, detec_init_APIC, and calibrating_APIC_clock Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
3491998dd5
commit
f28c0ae21d
2 changed files with 122 additions and 13 deletions
|
@ -66,6 +66,9 @@ static int __init parse_lapic(char *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
early_param("lapic", parse_lapic);
|
early_param("lapic", parse_lapic);
|
||||||
|
/* Local APIC was disabled by the BIOS and enabled by the kernel */
|
||||||
|
static int enabled_via_apicbase;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
|
@ -131,9 +134,6 @@ static struct clock_event_device lapic_clockevent = {
|
||||||
};
|
};
|
||||||
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
|
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
|
||||||
|
|
||||||
/* Local APIC was disabled by the BIOS and enabled by the kernel */
|
|
||||||
static int enabled_via_apicbase;
|
|
||||||
|
|
||||||
static unsigned long apic_phys;
|
static unsigned long apic_phys;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -240,6 +240,7 @@ void __cpuinit enable_NMI_through_LVT0(void)
|
||||||
apic_write(APIC_LVT0, v);
|
apic_write(APIC_LVT0, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
/**
|
/**
|
||||||
* get_physical_broadcast - Get number of physical broadcast IDs
|
* get_physical_broadcast - Get number of physical broadcast IDs
|
||||||
*/
|
*/
|
||||||
|
@ -247,6 +248,7 @@ int get_physical_broadcast(void)
|
||||||
{
|
{
|
||||||
return modern_apic() ? 0xff : 0xf;
|
return modern_apic() ? 0xff : 0xf;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lapic_get_maxlvt - get the maximum number of local vector table entries
|
* lapic_get_maxlvt - get the maximum number of local vector table entries
|
||||||
|
@ -1291,6 +1293,32 @@ no_apic:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
void __init early_init_lapic_mapping(void)
|
||||||
|
{
|
||||||
|
unsigned long phys_addr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no local APIC can be found then go out
|
||||||
|
* : it means there is no mpatable and MADT
|
||||||
|
*/
|
||||||
|
if (!smp_found_config)
|
||||||
|
return;
|
||||||
|
|
||||||
|
phys_addr = mp_lapic_addr;
|
||||||
|
|
||||||
|
set_fixmap_nocache(FIX_APIC_BASE, phys_addr);
|
||||||
|
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
|
||||||
|
APIC_BASE, phys_addr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch the APIC ID of the BSP in case we have a
|
||||||
|
* default configuration (or the MP table is broken).
|
||||||
|
*/
|
||||||
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init_apic_mappings - initialize APIC mappings
|
* init_apic_mappings - initialize APIC mappings
|
||||||
*/
|
*/
|
||||||
|
@ -1308,8 +1336,8 @@ void __init init_apic_mappings(void)
|
||||||
apic_phys = mp_lapic_addr;
|
apic_phys = mp_lapic_addr;
|
||||||
|
|
||||||
set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
|
set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
|
||||||
printk(KERN_DEBUG "mapped APIC to %08lx (%08lx)\n", APIC_BASE,
|
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
|
||||||
apic_phys);
|
APIC_BASE, apic_phys);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch the APIC ID of the BSP in case we have a
|
* Fetch the APIC ID of the BSP in case we have a
|
||||||
|
@ -1317,14 +1345,12 @@ void __init init_apic_mappings(void)
|
||||||
*/
|
*/
|
||||||
if (boot_cpu_physical_apicid == -1U)
|
if (boot_cpu_physical_apicid == -1U)
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This initializes the IO-APIC and APIC hardware if this is
|
* This initializes the IO-APIC and APIC hardware if this is
|
||||||
* a UP kernel.
|
* a UP kernel.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int apic_version[MAX_APICS];
|
int apic_version[MAX_APICS];
|
||||||
|
|
||||||
int __init APIC_init_uniprocessor(void)
|
int __init APIC_init_uniprocessor(void)
|
||||||
|
@ -1682,11 +1708,6 @@ static int lapic_resume(struct sys_device *dev)
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
if (x2apic)
|
|
||||||
enable_x2apic();
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Make sure the APICBASE points to the right address
|
* Make sure the APICBASE points to the right address
|
||||||
|
@ -1770,7 +1791,87 @@ static void apic_pm_activate(void) { }
|
||||||
|
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
/*
|
||||||
|
* apic_is_clustered_box() -- Check if we can expect good TSC
|
||||||
|
*
|
||||||
|
* Thus far, the major user of this is IBM's Summit2 series:
|
||||||
|
*
|
||||||
|
* Clustered boxes may have unsynced TSC problems if they are
|
||||||
|
* multi-chassis. Use available data to take a good guess.
|
||||||
|
* If in doubt, go HPET.
|
||||||
|
*/
|
||||||
|
__cpuinit int apic_is_clustered_box(void)
|
||||||
|
{
|
||||||
|
int i, clusters, zeros;
|
||||||
|
unsigned id;
|
||||||
|
u16 *bios_cpu_apicid;
|
||||||
|
DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* there is not this kind of box with AMD CPU yet.
|
||||||
|
* Some AMD box with quadcore cpu and 8 sockets apicid
|
||||||
|
* will be [4, 0x23] or [8, 0x27] could be thought to
|
||||||
|
* vsmp box still need checking...
|
||||||
|
*/
|
||||||
|
if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
|
||||||
|
bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
|
||||||
|
|
||||||
|
for (i = 0; i < NR_CPUS; i++) {
|
||||||
|
/* are we being called early in kernel startup? */
|
||||||
|
if (bios_cpu_apicid) {
|
||||||
|
id = bios_cpu_apicid[i];
|
||||||
|
}
|
||||||
|
else if (i < nr_cpu_ids) {
|
||||||
|
if (cpu_present(i))
|
||||||
|
id = per_cpu(x86_bios_cpu_apicid, i);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (id != BAD_APICID)
|
||||||
|
__set_bit(APIC_CLUSTERID(id), clustermap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Problem: Partially populated chassis may not have CPUs in some of
|
||||||
|
* the APIC clusters they have been allocated. Only present CPUs have
|
||||||
|
* x86_bios_cpu_apicid entries, thus causing zeroes in the bitmap.
|
||||||
|
* Since clusters are allocated sequentially, count zeros only if
|
||||||
|
* they are bounded by ones.
|
||||||
|
*/
|
||||||
|
clusters = 0;
|
||||||
|
zeros = 0;
|
||||||
|
for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
|
||||||
|
if (test_bit(i, clustermap)) {
|
||||||
|
clusters += 1 + zeros;
|
||||||
|
zeros = 0;
|
||||||
|
} else
|
||||||
|
++zeros;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
|
||||||
|
* not guaranteed to be synced between boards
|
||||||
|
*/
|
||||||
|
if (is_vsmp_box() && clusters > 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If clusters > 2, then should be multi-chassis.
|
||||||
|
* May have to revisit this when multi-core + hyperthreaded CPUs come
|
||||||
|
* out, but AFAIK this will work even for them.
|
||||||
|
*/
|
||||||
|
return (clusters > 2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* APIC command line parameters
|
||||||
|
*/
|
||||||
static int __init setup_disableapic(char *arg)
|
static int __init setup_disableapic(char *arg)
|
||||||
{
|
{
|
||||||
disable_apic = 1;
|
disable_apic = 1;
|
||||||
|
|
|
@ -69,6 +69,9 @@ static int __init parse_lapic(char *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
early_param("lapic", parse_lapic);
|
early_param("lapic", parse_lapic);
|
||||||
|
/* Local APIC was disabled by the BIOS and enabled by the kernel */
|
||||||
|
static int enabled_via_apicbase;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
|
@ -1279,6 +1282,7 @@ static int __init detect_init_APIC(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
void __init early_init_lapic_mapping(void)
|
void __init early_init_lapic_mapping(void)
|
||||||
{
|
{
|
||||||
unsigned long phys_addr;
|
unsigned long phys_addr;
|
||||||
|
@ -1302,6 +1306,7 @@ void __init early_init_lapic_mapping(void)
|
||||||
*/
|
*/
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init_apic_mappings - initialize APIC mappings
|
* init_apic_mappings - initialize APIC mappings
|
||||||
|
@ -1334,7 +1339,8 @@ void __init init_apic_mappings(void)
|
||||||
* Fetch the APIC ID of the BSP in case we have a
|
* Fetch the APIC ID of the BSP in case we have a
|
||||||
* default configuration (or the MP table is broken).
|
* default configuration (or the MP table is broken).
|
||||||
*/
|
*/
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
if (boot_cpu_physical_apicid == -1U)
|
||||||
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1782,6 +1788,7 @@ static void apic_pm_activate(void) { }
|
||||||
|
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
/*
|
/*
|
||||||
* apic_is_clustered_box() -- Check if we can expect good TSC
|
* apic_is_clustered_box() -- Check if we can expect good TSC
|
||||||
*
|
*
|
||||||
|
@ -1857,6 +1864,7 @@ __cpuinit int apic_is_clustered_box(void)
|
||||||
*/
|
*/
|
||||||
return (clusters > 2);
|
return (clusters > 2);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* APIC command line parameters
|
* APIC command line parameters
|
||||||
|
|
Loading…
Add table
Reference in a new issue