You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'x86/x2apic' into x86/core
Conflicts: include/asm-x86/i8259.h include/asm-x86/msidef.h Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -1420,6 +1420,12 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
|
||||
nolapic_timer [X86-32,APIC] Do not use the local APIC timer.
|
||||
|
||||
nox2apic [X86-64,APIC] Do not enable x2APIC mode.
|
||||
|
||||
x2apic_phys [X86-64,APIC] Use x2apic physical mode instead of
|
||||
default x2apic cluster mode on platforms
|
||||
supporting x2apic.
|
||||
|
||||
noltlbs [PPC] Do not use large page/tlb entries for kernel
|
||||
lowmem mapping on PPC40x.
|
||||
|
||||
|
||||
@@ -1652,6 +1652,14 @@ config DMAR_FLOPPY_WA
|
||||
workaround will setup a 1:1 mapping for the first
|
||||
16M to make floppy (an ISA device) work.
|
||||
|
||||
config INTR_REMAP
|
||||
bool "Support for Interrupt Remapping (EXPERIMENTAL)"
|
||||
depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
|
||||
help
|
||||
Supports Interrupt remapping for IO-APIC and MSI devices.
|
||||
To use x2apic mode in the CPU's which support x2APIC enhancements or
|
||||
to support platforms with CPU's having > 8 bit APIC ID, say Y.
|
||||
|
||||
source "drivers/pci/pcie/Kconfig"
|
||||
|
||||
source "drivers/pci/Kconfig"
|
||||
|
||||
@@ -104,6 +104,8 @@ obj-$(CONFIG_OLPC) += olpc.o
|
||||
ifeq ($(CONFIG_X86_64),y)
|
||||
obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o
|
||||
obj-y += bios_uv.o
|
||||
obj-y += genx2apic_cluster.o
|
||||
obj-y += genx2apic_phys.o
|
||||
obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
|
||||
obj-$(CONFIG_AUDIT) += audit_64.o
|
||||
|
||||
|
||||
@@ -761,7 +761,7 @@ static void __init acpi_register_lapic_address(unsigned long address)
|
||||
|
||||
set_fixmap_nocache(FIX_APIC_BASE, address);
|
||||
if (boot_cpu_physical_apicid == -1U) {
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
|
||||
boot_cpu_physical_apicid = read_apic_id();
|
||||
#ifdef CONFIG_X86_32
|
||||
apic_version[boot_cpu_physical_apicid] =
|
||||
GET_APIC_VERSION(apic_read(APIC_LVR));
|
||||
@@ -1337,7 +1337,9 @@ static void __init acpi_process_madt(void)
|
||||
acpi_ioapic = 1;
|
||||
|
||||
smp_found_config = 1;
|
||||
#ifdef CONFIG_X86_32
|
||||
setup_apic_routing();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (error == -EINVAL) {
|
||||
|
||||
@@ -145,13 +145,18 @@ static int modern_apic(void)
|
||||
return lapic_get_version() >= 0x14;
|
||||
}
|
||||
|
||||
void apic_wait_icr_idle(void)
|
||||
/*
|
||||
* Paravirt kernels also might be using these below ops. So we still
|
||||
* use generic apic_read()/apic_write(), which might be pointing to different
|
||||
* ops in PARAVIRT case.
|
||||
*/
|
||||
void xapic_wait_icr_idle(void)
|
||||
{
|
||||
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
u32 safe_apic_wait_icr_idle(void)
|
||||
u32 safe_xapic_wait_icr_idle(void)
|
||||
{
|
||||
u32 send_status;
|
||||
int timeout;
|
||||
@@ -167,6 +172,34 @@ u32 safe_apic_wait_icr_idle(void)
|
||||
return send_status;
|
||||
}
|
||||
|
||||
void xapic_icr_write(u32 low, u32 id)
|
||||
{
|
||||
apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id));
|
||||
apic_write(APIC_ICR, low);
|
||||
}
|
||||
|
||||
u64 xapic_icr_read(void)
|
||||
{
|
||||
u32 icr1, icr2;
|
||||
|
||||
icr2 = apic_read(APIC_ICR2);
|
||||
icr1 = apic_read(APIC_ICR);
|
||||
|
||||
return icr1 | ((u64)icr2 << 32);
|
||||
}
|
||||
|
||||
static struct apic_ops xapic_ops = {
|
||||
.read = native_apic_mem_read,
|
||||
.write = native_apic_mem_write,
|
||||
.icr_read = xapic_icr_read,
|
||||
.icr_write = xapic_icr_write,
|
||||
.wait_icr_idle = xapic_wait_icr_idle,
|
||||
.safe_wait_icr_idle = safe_xapic_wait_icr_idle,
|
||||
};
|
||||
|
||||
struct apic_ops __read_mostly *apic_ops = &xapic_ops;
|
||||
EXPORT_SYMBOL_GPL(apic_ops);
|
||||
|
||||
/**
|
||||
* enable_NMI_through_LVT0 - enable NMI through local vector table 0
|
||||
*/
|
||||
@@ -1205,7 +1238,7 @@ void __init init_apic_mappings(void)
|
||||
* default configuration (or the MP table is broken).
|
||||
*/
|
||||
if (boot_cpu_physical_apicid == -1U)
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
|
||||
boot_cpu_physical_apicid = read_apic_id();
|
||||
|
||||
}
|
||||
|
||||
@@ -1242,7 +1275,7 @@ int __init APIC_init_uniprocessor(void)
|
||||
* might be zero if read from MP tables. Get it from LAPIC.
|
||||
*/
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
|
||||
boot_cpu_physical_apicid = read_apic_id();
|
||||
#endif
|
||||
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
|
||||
|
||||
|
||||
+226
-11
@@ -27,6 +27,7 @@
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/acpi_pmtmr.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/dmar.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/smp.h>
|
||||
@@ -39,6 +40,7 @@
|
||||
#include <asm/proto.h>
|
||||
#include <asm/timex.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/i8259.h>
|
||||
|
||||
#include <mach_ipi.h>
|
||||
#include <mach_apic.h>
|
||||
@@ -46,6 +48,11 @@
|
||||
static int disable_apic_timer __cpuinitdata;
|
||||
static int apic_calibrate_pmtmr __initdata;
|
||||
int disable_apic;
|
||||
int disable_x2apic;
|
||||
int x2apic;
|
||||
|
||||
/* x2apic enabled before OS handover */
|
||||
int x2apic_preenabled;
|
||||
|
||||
/* Local APIC timer works in C2 */
|
||||
int local_apic_timer_c2_ok;
|
||||
@@ -119,13 +126,13 @@ static int modern_apic(void)
|
||||
return lapic_get_version() >= 0x14;
|
||||
}
|
||||
|
||||
void apic_wait_icr_idle(void)
|
||||
void xapic_wait_icr_idle(void)
|
||||
{
|
||||
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
u32 safe_apic_wait_icr_idle(void)
|
||||
u32 safe_xapic_wait_icr_idle(void)
|
||||
{
|
||||
u32 send_status;
|
||||
int timeout;
|
||||
@@ -141,6 +148,69 @@ u32 safe_apic_wait_icr_idle(void)
|
||||
return send_status;
|
||||
}
|
||||
|
||||
void xapic_icr_write(u32 low, u32 id)
|
||||
{
|
||||
apic_write(APIC_ICR2, id << 24);
|
||||
apic_write(APIC_ICR, low);
|
||||
}
|
||||
|
||||
u64 xapic_icr_read(void)
|
||||
{
|
||||
u32 icr1, icr2;
|
||||
|
||||
icr2 = apic_read(APIC_ICR2);
|
||||
icr1 = apic_read(APIC_ICR);
|
||||
|
||||
return (icr1 | ((u64)icr2 << 32));
|
||||
}
|
||||
|
||||
static struct apic_ops xapic_ops = {
|
||||
.read = native_apic_mem_read,
|
||||
.write = native_apic_mem_write,
|
||||
.icr_read = xapic_icr_read,
|
||||
.icr_write = xapic_icr_write,
|
||||
.wait_icr_idle = xapic_wait_icr_idle,
|
||||
.safe_wait_icr_idle = safe_xapic_wait_icr_idle,
|
||||
};
|
||||
|
||||
struct apic_ops __read_mostly *apic_ops = &xapic_ops;
|
||||
|
||||
EXPORT_SYMBOL_GPL(apic_ops);
|
||||
|
||||
static void x2apic_wait_icr_idle(void)
|
||||
{
|
||||
/* no need to wait for icr idle in x2apic */
|
||||
return;
|
||||
}
|
||||
|
||||
static u32 safe_x2apic_wait_icr_idle(void)
|
||||
{
|
||||
/* no need to wait for icr idle in x2apic */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void x2apic_icr_write(u32 low, u32 id)
|
||||
{
|
||||
wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
|
||||
}
|
||||
|
||||
u64 x2apic_icr_read(void)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static struct apic_ops x2apic_ops = {
|
||||
.read = native_apic_msr_read,
|
||||
.write = native_apic_msr_write,
|
||||
.icr_read = x2apic_icr_read,
|
||||
.icr_write = x2apic_icr_write,
|
||||
.wait_icr_idle = x2apic_wait_icr_idle,
|
||||
.safe_wait_icr_idle = safe_x2apic_wait_icr_idle,
|
||||
};
|
||||
|
||||
/**
|
||||
* enable_NMI_through_LVT0 - enable NMI through local vector table 0
|
||||
*/
|
||||
@@ -630,10 +700,10 @@ int __init verify_local_APIC(void)
|
||||
/*
|
||||
* The ID register is read/write in a real APIC.
|
||||
*/
|
||||
reg0 = read_apic_id();
|
||||
reg0 = apic_read(APIC_ID);
|
||||
apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
|
||||
apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
|
||||
reg1 = read_apic_id();
|
||||
reg1 = apic_read(APIC_ID);
|
||||
apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
|
||||
apic_write(APIC_ID, reg0);
|
||||
if (reg1 != (reg0 ^ APIC_ID_MASK))
|
||||
@@ -834,6 +904,125 @@ void __cpuinit end_local_APIC_setup(void)
|
||||
apic_pm_activate();
|
||||
}
|
||||
|
||||
void check_x2apic(void)
|
||||
{
|
||||
int msr, msr2;
|
||||
|
||||
rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
||||
|
||||
if (msr & X2APIC_ENABLE) {
|
||||
printk("x2apic enabled by BIOS, switching to x2apic ops\n");
|
||||
x2apic_preenabled = x2apic = 1;
|
||||
apic_ops = &x2apic_ops;
|
||||
}
|
||||
}
|
||||
|
||||
void enable_x2apic(void)
|
||||
{
|
||||
int msr, msr2;
|
||||
|
||||
rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
||||
if (!(msr & X2APIC_ENABLE)) {
|
||||
printk("Enabling x2apic\n");
|
||||
wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void enable_IR_x2apic(void)
|
||||
{
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
if (!cpu_has_x2apic)
|
||||
return;
|
||||
|
||||
if (!x2apic_preenabled && disable_x2apic) {
|
||||
printk(KERN_INFO
|
||||
"Skipped enabling x2apic and Interrupt-remapping "
|
||||
"because of nox2apic\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (x2apic_preenabled && disable_x2apic)
|
||||
panic("Bios already enabled x2apic, can't enforce nox2apic");
|
||||
|
||||
if (!x2apic_preenabled && skip_ioapic_setup) {
|
||||
printk(KERN_INFO
|
||||
"Skipped enabling x2apic and Interrupt-remapping "
|
||||
"because of skipping io-apic setup\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = dmar_table_init();
|
||||
if (ret) {
|
||||
printk(KERN_INFO
|
||||
"dmar_table_init() failed with %d:\n", ret);
|
||||
|
||||
if (x2apic_preenabled)
|
||||
panic("x2apic enabled by bios. But IR enabling failed");
|
||||
else
|
||||
printk(KERN_INFO
|
||||
"Not enabling x2apic,Intr-remapping\n");
|
||||
return;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
mask_8259A();
|
||||
save_mask_IO_APIC_setup();
|
||||
|
||||
ret = enable_intr_remapping(1);
|
||||
|
||||
if (ret && x2apic_preenabled) {
|
||||
local_irq_restore(flags);
|
||||
panic("x2apic enabled by bios. But IR enabling failed");
|
||||
}
|
||||
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
if (!x2apic) {
|
||||
x2apic = 1;
|
||||
apic_ops = &x2apic_ops;
|
||||
enable_x2apic();
|
||||
}
|
||||
end:
|
||||
if (ret)
|
||||
/*
|
||||
* IR enabling failed
|
||||
*/
|
||||
restore_IO_APIC_setup();
|
||||
else
|
||||
reinit_intr_remapped_IO_APIC(x2apic_preenabled);
|
||||
|
||||
unmask_8259A();
|
||||
local_irq_restore(flags);
|
||||
|
||||
if (!ret) {
|
||||
if (!x2apic_preenabled)
|
||||
printk(KERN_INFO
|
||||
"Enabled x2apic and interrupt-remapping\n");
|
||||
else
|
||||
printk(KERN_INFO
|
||||
"Enabled Interrupt-remapping\n");
|
||||
} else
|
||||
printk(KERN_ERR
|
||||
"Failed to enable Interrupt-remapping and x2apic\n");
|
||||
#else
|
||||
if (!cpu_has_x2apic)
|
||||
return;
|
||||
|
||||
if (x2apic_preenabled)
|
||||
panic("x2apic enabled prior OS handover,"
|
||||
" enable CONFIG_INTR_REMAP");
|
||||
|
||||
printk(KERN_INFO "Enable CONFIG_INTR_REMAP for enabling intr-remapping "
|
||||
" and x2apic\n");
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect and enable local APICs on non-SMP boards.
|
||||
* Original code written by Keir Fraser.
|
||||
@@ -873,7 +1062,7 @@ void __init early_init_lapic_mapping(void)
|
||||
* Fetch the APIC ID of the BSP in case we have a
|
||||
* default configuration (or the MP table is broken).
|
||||
*/
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
|
||||
boot_cpu_physical_apicid = read_apic_id();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -881,6 +1070,11 @@ void __init early_init_lapic_mapping(void)
|
||||
*/
|
||||
void __init init_apic_mappings(void)
|
||||
{
|
||||
if (x2apic) {
|
||||
boot_cpu_physical_apicid = read_apic_id();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no local APIC can be found then set up a fake all
|
||||
* zeroes page to simulate the local APIC and another
|
||||
@@ -900,7 +1094,7 @@ void __init init_apic_mappings(void)
|
||||
* Fetch the APIC ID of the BSP in case we have a
|
||||
* default configuration (or the MP table is broken).
|
||||
*/
|
||||
boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
|
||||
boot_cpu_physical_apicid = read_apic_id();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -919,6 +1113,9 @@ int __init APIC_init_uniprocessor(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
enable_IR_x2apic();
|
||||
setup_apic_routing();
|
||||
|
||||
verify_local_APIC();
|
||||
|
||||
connect_bsp_APIC();
|
||||
@@ -1100,6 +1297,11 @@ void __cpuinit generic_processor_info(int apicid, int version)
|
||||
cpu_set(cpu, cpu_present_map);
|
||||
}
|
||||
|
||||
int hard_smp_processor_id(void)
|
||||
{
|
||||
return read_apic_id();
|
||||
}
|
||||
|
||||
/*
|
||||
* Power management
|
||||
*/
|
||||
@@ -1136,7 +1338,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
|
||||
|
||||
maxlvt = lapic_get_maxlvt();
|
||||
|
||||
apic_pm_state.apic_id = read_apic_id();
|
||||
apic_pm_state.apic_id = apic_read(APIC_ID);
|
||||
apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI);
|
||||
apic_pm_state.apic_ldr = apic_read(APIC_LDR);
|
||||
apic_pm_state.apic_dfr = apic_read(APIC_DFR);
|
||||
@@ -1171,10 +1373,14 @@ static int lapic_resume(struct sys_device *dev)
|
||||
maxlvt = lapic_get_maxlvt();
|
||||
|
||||
local_irq_save(flags);
|
||||
rdmsr(MSR_IA32_APICBASE, l, h);
|
||||
l &= ~MSR_IA32_APICBASE_BASE;
|
||||
l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
|
||||
wrmsr(MSR_IA32_APICBASE, l, h);
|
||||
if (!x2apic) {
|
||||
rdmsr(MSR_IA32_APICBASE, l, h);
|
||||
l &= ~MSR_IA32_APICBASE_BASE;
|
||||
l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
|
||||
wrmsr(MSR_IA32_APICBASE, l, h);
|
||||
} else
|
||||
enable_x2apic();
|
||||
|
||||
apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
|
||||
apic_write(APIC_ID, apic_pm_state.apic_id);
|
||||
apic_write(APIC_DFR, apic_pm_state.apic_dfr);
|
||||
@@ -1314,6 +1520,15 @@ __cpuinit int apic_is_clustered_box(void)
|
||||
return (clusters > 2);
|
||||
}
|
||||
|
||||
static __init int setup_nox2apic(char *str)
|
||||
{
|
||||
disable_x2apic = 1;
|
||||
clear_cpu_cap(&boot_cpu_data, X86_FEATURE_X2APIC);
|
||||
return 0;
|
||||
}
|
||||
early_param("nox2apic", setup_nox2apic);
|
||||
|
||||
|
||||
/*
|
||||
* APIC command line parameters
|
||||
*/
|
||||
|
||||
@@ -597,6 +597,8 @@ void __cpuinit cpu_init(void)
|
||||
barrier();
|
||||
|
||||
check_efer();
|
||||
if (cpu != 0 && x2apic)
|
||||
enable_x2apic();
|
||||
|
||||
/*
|
||||
* set up and load the per-CPU TSS
|
||||
|
||||
@@ -45,7 +45,7 @@ const char * const x86_cap_flags[NCAPINTS*32] = {
|
||||
/* Intel-defined (#2) */
|
||||
"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
|
||||
"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
|
||||
NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
|
||||
NULL, NULL, "dca", "sse4_1", "sse4_2", "x2apic", NULL, "popcnt",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/* VIA/Cyrix/Centaur-defined */
|
||||
|
||||
@@ -21,81 +21,52 @@
|
||||
#include <asm/ipi.h>
|
||||
#include <asm/genapic.h>
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
#include <acpi/acpi_bus.h>
|
||||
#endif
|
||||
|
||||
DEFINE_PER_CPU(int, x2apic_extra_bits);
|
||||
extern struct genapic apic_flat;
|
||||
extern struct genapic apic_physflat;
|
||||
extern struct genapic apic_x2xpic_uv_x;
|
||||
extern struct genapic apic_x2apic_phys;
|
||||
extern struct genapic apic_x2apic_cluster;
|
||||
|
||||
struct genapic __read_mostly *genapic = &apic_flat;
|
||||
|
||||
static enum uv_system_type uv_system_type;
|
||||
static struct genapic *apic_probe[] __initdata = {
|
||||
&apic_x2apic_uv_x,
|
||||
&apic_x2apic_phys,
|
||||
&apic_x2apic_cluster,
|
||||
&apic_physflat,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
|
||||
*/
|
||||
void __init setup_apic_routing(void)
|
||||
{
|
||||
if (uv_system_type == UV_NON_UNIQUE_APIC)
|
||||
genapic = &apic_x2apic_uv_x;
|
||||
else
|
||||
#ifdef CONFIG_ACPI
|
||||
/*
|
||||
* Quirk: some x86_64 machines can only use physical APIC mode
|
||||
* regardless of how many processors are present (x86_64 ES7000
|
||||
* is an example).
|
||||
*/
|
||||
if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
|
||||
(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
|
||||
genapic = &apic_physflat;
|
||||
else
|
||||
#endif
|
||||
|
||||
if (max_physical_apicid < 8)
|
||||
genapic = &apic_flat;
|
||||
else
|
||||
genapic = &apic_physflat;
|
||||
|
||||
printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
|
||||
if (genapic == &apic_flat) {
|
||||
if (max_physical_apicid >= 8)
|
||||
genapic = &apic_physflat;
|
||||
printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Same for both flat and physical. */
|
||||
|
||||
void send_IPI_self(int vector)
|
||||
void apic_send_IPI_self(int vector)
|
||||
{
|
||||
__send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
|
||||
}
|
||||
|
||||
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;
|
||||
int i;
|
||||
|
||||
for (i = 0; apic_probe[i]; ++i) {
|
||||
if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
|
||||
genapic = apic_probe[i];
|
||||
printk(KERN_INFO "Setting APIC routing to %s.\n",
|
||||
genapic->name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int read_apic_id(void)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
WARN_ON(preemptible() && num_online_cpus() > 1);
|
||||
id = apic_read(APIC_ID);
|
||||
if (uv_system_type >= UV_X2APIC)
|
||||
id |= __get_cpu_var(x2apic_extra_bits);
|
||||
return id;
|
||||
}
|
||||
|
||||
enum uv_system_type get_uv_system_type(void)
|
||||
{
|
||||
return uv_system_type;
|
||||
}
|
||||
|
||||
int is_uv_system(void)
|
||||
{
|
||||
return uv_system_type != UV_NONE;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,20 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/ipi.h>
|
||||
#include <asm/genapic.h>
|
||||
#include <mach_apicdef.h>
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
#include <acpi/acpi_bus.h>
|
||||
#endif
|
||||
|
||||
static int __init flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static cpumask_t flat_target_cpus(void)
|
||||
{
|
||||
@@ -95,9 +106,33 @@ static void flat_send_IPI_all(int vector)
|
||||
__send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
|
||||
}
|
||||
|
||||
static unsigned int get_apic_id(unsigned long x)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
id = (((x)>>24) & 0xFFu);
|
||||
return id;
|
||||
}
|
||||
|
||||
static unsigned long set_apic_id(unsigned int id)
|
||||
{
|
||||
unsigned long x;
|
||||
|
||||
x = ((id & 0xFFu)<<24);
|
||||
return x;
|
||||
}
|
||||
|
||||
static unsigned int read_xapic_id(void)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
id = get_apic_id(apic_read(APIC_ID));
|
||||
return id;
|
||||
}
|
||||
|
||||
static int flat_apic_id_registered(void)
|
||||
{
|
||||
return physid_isset(GET_APIC_ID(read_apic_id()), phys_cpu_present_map);
|
||||
return physid_isset(read_xapic_id(), phys_cpu_present_map);
|
||||
}
|
||||
|
||||
static unsigned int flat_cpu_mask_to_apicid(cpumask_t cpumask)
|
||||
@@ -112,6 +147,7 @@ static unsigned int phys_pkg_id(int index_msb)
|
||||
|
||||
struct genapic apic_flat = {
|
||||
.name = "flat",
|
||||
.acpi_madt_oem_check = flat_acpi_madt_oem_check,
|
||||
.int_delivery_mode = dest_LowestPrio,
|
||||
.int_dest_mode = (APIC_DEST_LOGICAL != 0),
|
||||
.target_cpus = flat_target_cpus,
|
||||
@@ -121,8 +157,12 @@ struct genapic apic_flat = {
|
||||
.send_IPI_all = flat_send_IPI_all,
|
||||
.send_IPI_allbutself = flat_send_IPI_allbutself,
|
||||
.send_IPI_mask = flat_send_IPI_mask,
|
||||
.send_IPI_self = apic_send_IPI_self,
|
||||
.cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
|
||||
.phys_pkg_id = phys_pkg_id,
|
||||
.get_apic_id = get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
.apic_id_mask = (0xFFu<<24),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -130,6 +170,21 @@ struct genapic apic_flat = {
|
||||
* We cannot use logical delivery in this case because the mask
|
||||
* overflows, so use physical mode.
|
||||
*/
|
||||
static int __init physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
#ifdef CONFIG_ACPI
|
||||
/*
|
||||
* Quirk: some x86_64 machines can only use physical APIC mode
|
||||
* regardless of how many processors are present (x86_64 ES7000
|
||||
* is an example).
|
||||
*/
|
||||
if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
|
||||
(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cpumask_t physflat_target_cpus(void)
|
||||
{
|
||||
@@ -176,6 +231,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
|
||||
|
||||
struct genapic apic_physflat = {
|
||||
.name = "physical flat",
|
||||
.acpi_madt_oem_check = physflat_acpi_madt_oem_check,
|
||||
.int_delivery_mode = dest_Fixed,
|
||||
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
|
||||
.target_cpus = physflat_target_cpus,
|
||||
@@ -185,6 +241,10 @@ struct genapic apic_physflat = {
|
||||
.send_IPI_all = physflat_send_IPI_all,
|
||||
.send_IPI_allbutself = physflat_send_IPI_allbutself,
|
||||
.send_IPI_mask = physflat_send_IPI_mask,
|
||||
.send_IPI_self = apic_send_IPI_self,
|
||||
.cpu_mask_to_apicid = physflat_cpu_mask_to_apicid,
|
||||
.phys_pkg_id = phys_pkg_id,
|
||||
.get_apic_id = get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
.apic_id_mask = (0xFFu<<24),
|
||||
};
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
#include <linux/threads.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/dmar.h>
|
||||
|
||||
#include <asm/smp.h>
|
||||
#include <asm/ipi.h>
|
||||
#include <asm/genapic.h>
|
||||
|
||||
DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
|
||||
|
||||
static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
if (cpu_has_x2apic && intr_remapping_enabled)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
|
||||
|
||||
static cpumask_t x2apic_target_cpus(void)
|
||||
{
|
||||
return cpumask_of_cpu(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* for now each logical cpu is in its own vector allocation domain.
|
||||
*/
|
||||
static cpumask_t x2apic_vector_allocation_domain(int cpu)
|
||||
{
|
||||
cpumask_t domain = CPU_MASK_NONE;
|
||||
cpu_set(cpu, domain);
|
||||
return domain;
|
||||
}
|
||||
|
||||
static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
|
||||
unsigned int dest)
|
||||
{
|
||||
unsigned long cfg;
|
||||
|
||||
cfg = __prepare_ICR(0, vector, dest);
|
||||
|
||||
/*
|
||||
* send the IPI.
|
||||
*/
|
||||
x2apic_icr_write(cfg, apicid);
|
||||
}
|
||||
|
||||
/*
|
||||
* for now, we send the IPI's one by one in the cpumask.
|
||||
* TBD: Based on the cpu mask, we can send the IPI's to the cluster group
|
||||
* at once. We have 16 cpu's in a cluster. This will minimize IPI register
|
||||
* writes.
|
||||
*/
|
||||
static void x2apic_send_IPI_mask(cpumask_t mask, int vector)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long query_cpu;
|
||||
|
||||
local_irq_save(flags);
|
||||
for_each_cpu_mask(query_cpu, mask) {
|
||||
__x2apic_send_IPI_dest(per_cpu(x86_cpu_to_logical_apicid, query_cpu),
|
||||
vector, APIC_DEST_LOGICAL);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void x2apic_send_IPI_allbutself(int vector)
|
||||
{
|
||||
cpumask_t mask = cpu_online_map;
|
||||
|
||||
cpu_clear(smp_processor_id(), mask);
|
||||
|
||||
if (!cpus_empty(mask))
|
||||
x2apic_send_IPI_mask(mask, vector);
|
||||
}
|
||||
|
||||
static void x2apic_send_IPI_all(int vector)
|
||||
{
|
||||
x2apic_send_IPI_mask(cpu_online_map, vector);
|
||||
}
|
||||
|
||||
static int x2apic_apic_id_registered(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
/*
|
||||
* We're using fixed IRQ delivery, can only return one phys APIC ID.
|
||||
* May as well be the first.
|
||||
*/
|
||||
cpu = first_cpu(cpumask);
|
||||
if ((unsigned)cpu < NR_CPUS)
|
||||
return per_cpu(x86_cpu_to_logical_apicid, cpu);
|
||||
else
|
||||
return BAD_APICID;
|
||||
}
|
||||
|
||||
static unsigned int get_apic_id(unsigned long x)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
id = x;
|
||||
return id;
|
||||
}
|
||||
|
||||
static unsigned long set_apic_id(unsigned int id)
|
||||
{
|
||||
unsigned long x;
|
||||
|
||||
x = id;
|
||||
return x;
|
||||
}
|
||||
|
||||
static unsigned int x2apic_read_id(void)
|
||||
{
|
||||
return apic_read(APIC_ID);
|
||||
}
|
||||
|
||||
static unsigned int phys_pkg_id(int index_msb)
|
||||
{
|
||||
return x2apic_read_id() >> index_msb;
|
||||
}
|
||||
|
||||
static void x2apic_send_IPI_self(int vector)
|
||||
{
|
||||
apic_write(APIC_SELF_IPI, vector);
|
||||
}
|
||||
|
||||
static void init_x2apic_ldr(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
per_cpu(x86_cpu_to_logical_apicid, cpu) = apic_read(APIC_LDR);
|
||||
return;
|
||||
}
|
||||
|
||||
struct genapic apic_x2apic_cluster = {
|
||||
.name = "cluster x2apic",
|
||||
.acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
|
||||
.int_delivery_mode = dest_LowestPrio,
|
||||
.int_dest_mode = (APIC_DEST_LOGICAL != 0),
|
||||
.target_cpus = x2apic_target_cpus,
|
||||
.vector_allocation_domain = x2apic_vector_allocation_domain,
|
||||
.apic_id_registered = x2apic_apic_id_registered,
|
||||
.init_apic_ldr = init_x2apic_ldr,
|
||||
.send_IPI_all = x2apic_send_IPI_all,
|
||||
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
|
||||
.send_IPI_mask = x2apic_send_IPI_mask,
|
||||
.send_IPI_self = x2apic_send_IPI_self,
|
||||
.cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid,
|
||||
.phys_pkg_id = phys_pkg_id,
|
||||
.get_apic_id = get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
.apic_id_mask = (0xFFFFFFFFu),
|
||||
};
|
||||
@@ -0,0 +1,159 @@
|
||||
#include <linux/threads.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/dmar.h>
|
||||
|
||||
#include <asm/smp.h>
|
||||
#include <asm/ipi.h>
|
||||
#include <asm/genapic.h>
|
||||
|
||||
static int x2apic_phys;
|
||||
|
||||
static int set_x2apic_phys_mode(char *arg)
|
||||
{
|
||||
x2apic_phys = 1;
|
||||
return 0;
|
||||
}
|
||||
early_param("x2apic_phys", set_x2apic_phys_mode);
|
||||
|
||||
static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
if (cpu_has_x2apic && intr_remapping_enabled && x2apic_phys)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
|
||||
|
||||
static cpumask_t x2apic_target_cpus(void)
|
||||
{
|
||||
return cpumask_of_cpu(0);
|
||||
}
|
||||
|
||||
static cpumask_t x2apic_vector_allocation_domain(int cpu)
|
||||
{
|
||||
cpumask_t domain = CPU_MASK_NONE;
|
||||
cpu_set(cpu, domain);
|
||||
return domain;
|
||||
}
|
||||
|
||||
static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
|
||||
unsigned int dest)
|
||||
{
|
||||
unsigned long cfg;
|
||||
|
||||
cfg = __prepare_ICR(0, vector, dest);
|
||||
|
||||
/*
|
||||
* send the IPI.
|
||||
*/
|
||||
x2apic_icr_write(cfg, apicid);
|
||||
}
|
||||
|
||||
static void x2apic_send_IPI_mask(cpumask_t mask, int vector)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long query_cpu;
|
||||
|
||||
local_irq_save(flags);
|
||||
for_each_cpu_mask(query_cpu, mask) {
|
||||
__x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu),
|
||||
vector, APIC_DEST_PHYSICAL);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void x2apic_send_IPI_allbutself(int vector)
|
||||
{
|
||||
cpumask_t mask = cpu_online_map;
|
||||
|
||||
cpu_clear(smp_processor_id(), mask);
|
||||
|
||||
if (!cpus_empty(mask))
|
||||
x2apic_send_IPI_mask(mask, vector);
|
||||
}
|
||||
|
||||
static void x2apic_send_IPI_all(int vector)
|
||||
{
|
||||
x2apic_send_IPI_mask(cpu_online_map, vector);
|
||||
}
|
||||
|
||||
static int x2apic_apic_id_registered(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
/*
|
||||
* We're using fixed IRQ delivery, can only return one phys APIC ID.
|
||||
* May as well be the first.
|
||||
*/
|
||||
cpu = first_cpu(cpumask);
|
||||
if ((unsigned)cpu < NR_CPUS)
|
||||
return per_cpu(x86_cpu_to_apicid, cpu);
|
||||
else
|
||||
return BAD_APICID;
|
||||
}
|
||||
|
||||
static unsigned int get_apic_id(unsigned long x)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
id = x;
|
||||
return id;
|
||||
}
|
||||
|
||||
static unsigned long set_apic_id(unsigned int id)
|
||||
{
|
||||
unsigned long x;
|
||||
|
||||
x = id;
|
||||
return x;
|
||||
}
|
||||
|
||||
static unsigned int x2apic_read_id(void)
|
||||
{
|
||||
return apic_read(APIC_ID);
|
||||
}
|
||||
|
||||
static unsigned int phys_pkg_id(int index_msb)
|
||||
{
|
||||
return x2apic_read_id() >> index_msb;
|
||||
}
|
||||
|
||||
void x2apic_send_IPI_self(int vector)
|
||||
{
|
||||
apic_write(APIC_SELF_IPI, vector);
|
||||
}
|
||||
|
||||
void init_x2apic_ldr(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct genapic apic_x2apic_phys = {
|
||||
.name = "physical x2apic",
|
||||
.acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
|
||||
.int_delivery_mode = dest_Fixed,
|
||||
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
|
||||
.target_cpus = x2apic_target_cpus,
|
||||
.vector_allocation_domain = x2apic_vector_allocation_domain,
|
||||
.apic_id_registered = x2apic_apic_id_registered,
|
||||
.init_apic_ldr = init_x2apic_ldr,
|
||||
.send_IPI_all = x2apic_send_IPI_all,
|
||||
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
|
||||
.send_IPI_mask = x2apic_send_IPI_mask,
|
||||
.send_IPI_self = x2apic_send_IPI_self,
|
||||
.cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid,
|
||||
.phys_pkg_id = phys_pkg_id,
|
||||
.get_apic_id = get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
.apic_id_mask = (0xFFFFFFFFu),
|
||||
};
|
||||
@@ -12,12 +12,12 @@
|
||||
#include <linux/threads.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/ipi.h>
|
||||
#include <asm/genapic.h>
|
||||
@@ -26,6 +26,35 @@
|
||||
#include <asm/uv/uv_hub.h>
|
||||
#include <asm/uv/bios.h>
|
||||
|
||||
DEFINE_PER_CPU(int, x2apic_extra_bits);
|
||||
|
||||
static enum uv_system_type uv_system_type;
|
||||
|
||||
static int __init uv_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 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum uv_system_type get_uv_system_type(void)
|
||||
{
|
||||
return uv_system_type;
|
||||
}
|
||||
|
||||
int is_uv_system(void)
|
||||
{
|
||||
return uv_system_type != UV_NONE;
|
||||
}
|
||||
|
||||
DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
|
||||
EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
|
||||
|
||||
@@ -123,6 +152,10 @@ static int uv_apic_id_registered(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void uv_init_apic_ldr(void)
|
||||
{
|
||||
}
|
||||
|
||||
static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
|
||||
{
|
||||
int cpu;
|
||||
@@ -138,9 +171,34 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
|
||||
return BAD_APICID;
|
||||
}
|
||||
|
||||
static unsigned int get_apic_id(unsigned long x)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
WARN_ON(preemptible() && num_online_cpus() > 1);
|
||||
id = x | __get_cpu_var(x2apic_extra_bits);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static unsigned long set_apic_id(unsigned int id)
|
||||
{
|
||||
unsigned long x;
|
||||
|
||||
/* maskout x2apic_extra_bits ? */
|
||||
x = id;
|
||||
return x;
|
||||
}
|
||||
|
||||
static unsigned int uv_read_apic_id(void)
|
||||
{
|
||||
|
||||
return get_apic_id(apic_read(APIC_ID));
|
||||
}
|
||||
|
||||
static unsigned int phys_pkg_id(int index_msb)
|
||||
{
|
||||
return GET_APIC_ID(read_apic_id()) >> index_msb;
|
||||
return uv_read_apic_id() >> index_msb;
|
||||
}
|
||||
|
||||
#ifdef ZZZ /* Needs x2apic patch */
|
||||
@@ -152,17 +210,22 @@ static void uv_send_IPI_self(int vector)
|
||||
|
||||
struct genapic apic_x2apic_uv_x = {
|
||||
.name = "UV large system",
|
||||
.acpi_madt_oem_check = uv_acpi_madt_oem_check,
|
||||
.int_delivery_mode = dest_Fixed,
|
||||
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
|
||||
.target_cpus = uv_target_cpus,
|
||||
.vector_allocation_domain = uv_vector_allocation_domain,/* Fixme ZZZ */
|
||||
.apic_id_registered = uv_apic_id_registered,
|
||||
.init_apic_ldr = uv_init_apic_ldr,
|
||||
.send_IPI_all = uv_send_IPI_all,
|
||||
.send_IPI_allbutself = uv_send_IPI_allbutself,
|
||||
.send_IPI_mask = uv_send_IPI_mask,
|
||||
/* ZZZ.send_IPI_self = uv_send_IPI_self, */
|
||||
.cpu_mask_to_apicid = uv_cpu_mask_to_apicid,
|
||||
.phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */
|
||||
.get_apic_id = get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
.apic_id_mask = (0xFFFFFFFFu),
|
||||
};
|
||||
|
||||
static __cpuinit void set_x2apic_extra_bits(int pnode)
|
||||
@@ -399,3 +462,5 @@ void __cpuinit uv_cpu_init(void)
|
||||
if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
|
||||
set_x2apic_extra_bits(uv_hub_info->pnode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -282,6 +282,30 @@ static int __init i8259A_init_sysfs(void)
|
||||
|
||||
device_initcall(i8259A_init_sysfs);
|
||||
|
||||
void mask_8259A(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&i8259A_lock, flags);
|
||||
|
||||
outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
|
||||
outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */
|
||||
|
||||
spin_unlock_irqrestore(&i8259A_lock, flags);
|
||||
}
|
||||
|
||||
void unmask_8259A(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&i8259A_lock, flags);
|
||||
|
||||
outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
|
||||
outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */
|
||||
|
||||
spin_unlock_irqrestore(&i8259A_lock, flags);
|
||||
}
|
||||
|
||||
void init_8259A(int auto_eoi)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@@ -1494,7 +1494,7 @@ void /*__init*/ print_local_APIC(void *dummy)
|
||||
smp_processor_id(), hard_smp_processor_id());
|
||||
v = apic_read(APIC_ID);
|
||||
printk(KERN_INFO "... APIC ID: %08x (%01x)\n", v,
|
||||
GET_APIC_ID(read_apic_id()));
|
||||
GET_APIC_ID(v));
|
||||
v = apic_read(APIC_LVR);
|
||||
printk(KERN_INFO "... APIC VERSION: %08x\n", v);
|
||||
ver = GET_APIC_VERSION(v);
|
||||
@@ -1702,8 +1702,7 @@ void disable_IO_APIC(void)
|
||||
entry.dest_mode = 0; /* Physical */
|
||||
entry.delivery_mode = dest_ExtINT; /* ExtInt */
|
||||
entry.vector = 0;
|
||||
entry.dest.physical.physical_dest =
|
||||
GET_APIC_ID(read_apic_id());
|
||||
entry.dest.physical.physical_dest = read_apic_id();
|
||||
|
||||
/*
|
||||
* Add it to the IO-APIC irq-routing table:
|
||||
|
||||
+576
-40
File diff suppressed because it is too large
Load Diff
@@ -397,7 +397,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
|
||||
generic_bigsmp_probe();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
setup_apic_routing();
|
||||
#endif
|
||||
if (!num_processors)
|
||||
printk(KERN_ERR "MPTABLE: no processors registered!\n");
|
||||
return num_processors;
|
||||
|
||||
@@ -373,8 +373,6 @@ struct pv_cpu_ops pv_cpu_ops = {
|
||||
|
||||
struct pv_apic_ops pv_apic_ops = {
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
.apic_write = native_apic_write,
|
||||
.apic_read = native_apic_read,
|
||||
.setup_boot_clock = setup_boot_APIC_clock,
|
||||
.setup_secondary_clock = setup_secondary_APIC_clock,
|
||||
.startup_ipi_hook = paravirt_nop,
|
||||
|
||||
@@ -731,6 +731,8 @@ void __init setup_arch(char **cmdline_p)
|
||||
num_physpages = max_pfn;
|
||||
|
||||
check_efer();
|
||||
if (cpu_has_x2apic)
|
||||
check_x2apic();
|
||||
|
||||
/* How many end-of-memory variables you have, grandma! */
|
||||
/* need this before calling reserve_initrd */
|
||||
|
||||
+19
-19
@@ -123,7 +123,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
|
||||
|
||||
static atomic_t init_deasserted;
|
||||
|
||||
static int boot_cpu_logical_apicid;
|
||||
|
||||
/* representing cpus for which sibling maps can be computed */
|
||||
static cpumask_t cpu_sibling_setup_map;
|
||||
@@ -165,6 +164,8 @@ static void unmap_cpu_to_node(int cpu)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
static int boot_cpu_logical_apicid;
|
||||
|
||||
u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
|
||||
{ [0 ... NR_CPUS-1] = BAD_APICID };
|
||||
|
||||
@@ -210,7 +211,7 @@ static void __cpuinit smp_callin(void)
|
||||
/*
|
||||
* (This works even if the APIC is not enabled.)
|
||||
*/
|
||||
phys_id = GET_APIC_ID(read_apic_id());
|
||||
phys_id = read_apic_id();
|
||||
cpuid = smp_processor_id();
|
||||
if (cpu_isset(cpuid, cpu_callin_map)) {
|
||||
panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
|
||||
@@ -546,8 +547,7 @@ static inline void __inquire_remote_apic(int apicid)
|
||||
printk(KERN_CONT
|
||||
"a previous APIC delivery may have failed\n");
|
||||
|
||||
apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
|
||||
apic_write(APIC_ICR, APIC_DM_REMRD | regs[i]);
|
||||
apic_icr_write(APIC_DM_REMRD | regs[i], apicid);
|
||||
|
||||
timeout = 0;
|
||||
do {
|
||||
@@ -579,11 +579,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
|
||||
int maxlvt;
|
||||
|
||||
/* Target chip */
|
||||
apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
|
||||
|
||||
/* Boot on the stack */
|
||||
/* Kick the second */
|
||||
apic_write(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
|
||||
apic_icr_write(APIC_DM_NMI | APIC_DEST_LOGICAL, logical_apicid);
|
||||
|
||||
pr_debug("Waiting for send to finish...\n");
|
||||
send_status = safe_apic_wait_icr_idle();
|
||||
@@ -636,13 +634,11 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
|
||||
/*
|
||||
* Turn INIT on target chip
|
||||
*/
|
||||
apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
|
||||
|
||||
/*
|
||||
* Send IPI
|
||||
*/
|
||||
apic_write(APIC_ICR,
|
||||
APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
|
||||
apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT,
|
||||
phys_apicid);
|
||||
|
||||
pr_debug("Waiting for send to finish...\n");
|
||||
send_status = safe_apic_wait_icr_idle();
|
||||
@@ -652,10 +648,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
|
||||
pr_debug("Deasserting INIT.\n");
|
||||
|
||||
/* Target chip */
|
||||
apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
|
||||
|
||||
/* Send IPI */
|
||||
apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
|
||||
apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid);
|
||||
|
||||
pr_debug("Waiting for send to finish...\n");
|
||||
send_status = safe_apic_wait_icr_idle();
|
||||
@@ -698,11 +692,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
|
||||
*/
|
||||
|
||||
/* Target chip */
|
||||
apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
|
||||
|
||||
/* Boot on the stack */
|
||||
/* Kick the second */
|
||||
apic_write(APIC_ICR, APIC_DM_STARTUP | (start_eip >> 12));
|
||||
apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12),
|
||||
phys_apicid);
|
||||
|
||||
/*
|
||||
* Give the other CPU some time to accept the IPI.
|
||||
@@ -1136,10 +1129,17 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
|
||||
* Setup boot CPU information
|
||||
*/
|
||||
smp_store_cpu_info(0); /* Final full version of the data */
|
||||
#ifdef CONFIG_X86_32
|
||||
boot_cpu_logical_apicid = logical_smp_processor_id();
|
||||
#endif
|
||||
current_thread_info()->cpu = 0; /* needed? */
|
||||
set_cpu_sibling_map(0);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
enable_IR_x2apic();
|
||||
setup_apic_routing();
|
||||
#endif
|
||||
|
||||
if (smp_sanity_check(max_cpus) < 0) {
|
||||
printk(KERN_INFO "SMP disabled\n");
|
||||
disable_smp();
|
||||
@@ -1147,9 +1147,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
|
||||
}
|
||||
|
||||
preempt_disable();
|
||||
if (GET_APIC_ID(read_apic_id()) != boot_cpu_physical_apicid) {
|
||||
if (read_apic_id() != boot_cpu_physical_apicid) {
|
||||
panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
|
||||
GET_APIC_ID(read_apic_id()), boot_cpu_physical_apicid);
|
||||
read_apic_id(), boot_cpu_physical_apicid);
|
||||
/* Or can we switch back to PIC here? */
|
||||
}
|
||||
preempt_enable();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user