x64, x2apic/intr-remap: x2apic ops for x2apic mode support

x2apic ops for x2apic mode support. This uses MSR interface and differs
slightly from the xapic register layout.

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: akpm@linux-foundation.org
Cc: arjan@linux.intel.com
Cc: andi@firstfloor.org
Cc: ebiederm@xmission.com
Cc: jbarnes@virtuousgeek.org
Cc: steiner@sgi.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Suresh Siddha 2008-07-10 11:16:52 -07:00 committed by Ingo Molnar
parent 1cb11583a6
commit 13c88fb58d
3 changed files with 60 additions and 0 deletions

View File

@ -171,6 +171,41 @@ struct apic_ops __read_mostly *apic_ops = &xapic_ops;
EXPORT_SYMBOL_GPL(apic_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,
.write_atomic = 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 * enable_NMI_through_LVT0 - enable NMI through local vector table 0
*/ */

View File

@ -7,6 +7,8 @@
#include <asm/apicdef.h> #include <asm/apicdef.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/cpufeature.h>
#include <asm/msr.h>
#define ARCH_APICTIMER_STOPS_ON_C3 1 #define ARCH_APICTIMER_STOPS_ON_C3 1
@ -73,6 +75,26 @@ static inline u32 native_apic_mem_read(u32 reg)
return *((volatile u32 *)(APIC_BASE + reg)); return *((volatile u32 *)(APIC_BASE + reg));
} }
static inline void native_apic_msr_write(u32 reg, u32 v)
{
if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR ||
reg == APIC_LVR)
return;
wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0);
}
static inline u32 native_apic_msr_read(u32 reg)
{
u32 low, high;
if (reg == APIC_DFR)
return -1;
rdmsr(APIC_BASE_MSR + (reg >> 4), low, high);
return low;
}
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
extern void apic_wait_icr_idle(void); extern void apic_wait_icr_idle(void);
extern u32 safe_apic_wait_icr_idle(void); extern u32 safe_apic_wait_icr_idle(void);

View File

@ -105,6 +105,7 @@
#define APIC_TMICT 0x380 #define APIC_TMICT 0x380
#define APIC_TMCCT 0x390 #define APIC_TMCCT 0x390
#define APIC_TDCR 0x3E0 #define APIC_TDCR 0x3E0
#define APIC_SELF_IPI 0x3F0
#define APIC_TDR_DIV_TMBASE (1 << 2) #define APIC_TDR_DIV_TMBASE (1 << 2)
#define APIC_TDR_DIV_1 0xB #define APIC_TDR_DIV_1 0xB
#define APIC_TDR_DIV_2 0x0 #define APIC_TDR_DIV_2 0x0
@ -128,6 +129,8 @@
#define APIC_EILVT3 0x530 #define APIC_EILVT3 0x530
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
#define APIC_BASE_MSR 0x800
#define X2APIC_ENABLE (1UL << 10)
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
# define MAX_IO_APICS 64 # define MAX_IO_APICS 64