]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Suresh Siddha <suresh.b.siddha@intel.com> |
2 | Subject: x64, x2apic/intr-remap: x2apic ops for x2apic mode support | |
3 | References: fate #303948 and fate #303984 | |
4 | Patch-Mainline: queued for .28 | |
5 | Commit-ID: 13c88fb58d0112d47f7839f24a755715c6218822 | |
6 | ||
7 | Signed-off-by: Thomas Renninger <trenn@suse.de> | |
8 | ||
9 | x2apic ops for x2apic mode support. This uses MSR interface and differs | |
10 | slightly from the xapic register layout. | |
11 | ||
12 | Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> | |
13 | Cc: akpm@linux-foundation.org | |
14 | Cc: arjan@linux.intel.com | |
15 | Cc: andi@firstfloor.org | |
16 | Cc: ebiederm@xmission.com | |
17 | Cc: jbarnes@virtuousgeek.org | |
18 | Cc: steiner@sgi.com | |
19 | Signed-off-by: Ingo Molnar <mingo@elte.hu> | |
20 | ||
21 | --- | |
22 | arch/x86/kernel/apic_64.c | 35 +++++++++++++++++++++++++++++++++++ | |
23 | include/asm-x86/apic.h | 23 +++++++++++++++++++++++ | |
24 | include/asm-x86/apicdef.h | 3 +++ | |
25 | 3 files changed, 61 insertions(+) | |
26 | ||
27 | Index: linux-2.6.26/arch/x86/kernel/apic_64.c | |
28 | =================================================================== | |
29 | --- linux-2.6.26.orig/arch/x86/kernel/apic_64.c | |
30 | +++ linux-2.6.26/arch/x86/kernel/apic_64.c | |
31 | @@ -169,6 +169,41 @@ struct apic_ops __read_mostly *apic_ops | |
32 | ||
33 | EXPORT_SYMBOL_GPL(apic_ops); | |
34 | ||
35 | +static void x2apic_wait_icr_idle(void) | |
36 | +{ | |
37 | + /* no need to wait for icr idle in x2apic */ | |
38 | + return; | |
39 | +} | |
40 | + | |
41 | +static u32 safe_x2apic_wait_icr_idle(void) | |
42 | +{ | |
43 | + /* no need to wait for icr idle in x2apic */ | |
44 | + return 0; | |
45 | +} | |
46 | + | |
47 | +void x2apic_icr_write(u32 low, u32 id) | |
48 | +{ | |
49 | + wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low); | |
50 | +} | |
51 | + | |
52 | +u64 x2apic_icr_read(void) | |
53 | +{ | |
54 | + unsigned long val; | |
55 | + | |
56 | + rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val); | |
57 | + return val; | |
58 | +} | |
59 | + | |
60 | +static struct apic_ops x2apic_ops = { | |
61 | + .read = native_apic_msr_read, | |
62 | + .write = native_apic_msr_write, | |
63 | + .write_atomic = native_apic_msr_write, | |
64 | + .icr_read = x2apic_icr_read, | |
65 | + .icr_write = x2apic_icr_write, | |
66 | + .wait_icr_idle = x2apic_wait_icr_idle, | |
67 | + .safe_wait_icr_idle = safe_x2apic_wait_icr_idle, | |
68 | +}; | |
69 | + | |
70 | /** | |
71 | * enable_NMI_through_LVT0 - enable NMI through local vector table 0 | |
72 | */ | |
73 | Index: linux-2.6.26/include/asm-x86/apic.h | |
74 | =================================================================== | |
75 | --- linux-2.6.26.orig/include/asm-x86/apic.h | |
76 | +++ linux-2.6.26/include/asm-x86/apic.h | |
77 | @@ -9,6 +9,8 @@ | |
78 | #include <asm/apicdef.h> | |
79 | #include <asm/processor.h> | |
80 | #include <asm/system.h> | |
81 | +#include <asm/cpufeature.h> | |
82 | +#include <asm/msr.h> | |
83 | ||
84 | #define ARCH_APICTIMER_STOPS_ON_C3 1 | |
85 | ||
86 | @@ -71,11 +73,32 @@ static inline u32 native_apic_mem_read(u | |
87 | return *((volatile u32 *)(APIC_BASE + reg)); | |
88 | } | |
89 | ||
90 | +static inline void native_apic_msr_write(u32 reg, u32 v) | |
91 | +{ | |
92 | + if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR || | |
93 | + reg == APIC_LVR) | |
94 | + return; | |
95 | + | |
96 | + wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0); | |
97 | +} | |
98 | + | |
99 | +static inline u32 native_apic_msr_read(u32 reg) | |
100 | +{ | |
101 | + u32 low, high; | |
102 | + | |
103 | + if (reg == APIC_DFR) | |
104 | + return -1; | |
105 | + | |
106 | + rdmsr(APIC_BASE_MSR + (reg >> 4), low, high); | |
107 | + return low; | |
108 | +} | |
109 | + | |
110 | #ifdef CONFIG_X86_32 | |
111 | extern void apic_wait_icr_idle(void); | |
112 | extern u32 safe_apic_wait_icr_idle(void); | |
113 | extern void apic_icr_write(u32 low, u32 id); | |
114 | #else | |
115 | +extern void x2apic_icr_write(u32 low, u32 id); | |
116 | ||
117 | struct apic_ops { | |
118 | u32 (*read)(u32 reg); | |
119 | Index: linux-2.6.26/include/asm-x86/apicdef.h | |
120 | =================================================================== | |
121 | --- linux-2.6.26.orig/include/asm-x86/apicdef.h | |
122 | +++ linux-2.6.26/include/asm-x86/apicdef.h | |
123 | @@ -105,6 +105,7 @@ | |
124 | #define APIC_TMICT 0x380 | |
125 | #define APIC_TMCCT 0x390 | |
126 | #define APIC_TDCR 0x3E0 | |
127 | +#define APIC_SELF_IPI 0x3F0 | |
128 | #define APIC_TDR_DIV_TMBASE (1 << 2) | |
129 | #define APIC_TDR_DIV_1 0xB | |
130 | #define APIC_TDR_DIV_2 0x0 | |
131 | @@ -128,6 +129,8 @@ | |
132 | #define APIC_EILVT3 0x530 | |
133 | ||
134 | #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) | |
135 | +#define APIC_BASE_MSR 0x800 | |
136 | +#define X2APIC_ENABLE (1UL << 10) | |
137 | ||
138 | #ifdef CONFIG_X86_32 | |
139 | # define MAX_IO_APICS 64 |