aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/apic_32.c6
-rw-r--r--arch/x86/kernel/apic_64.c34
-rw-r--r--arch/x86/kernel/io_apic_64.c8
-rw-r--r--arch/x86/kernel/paravirt.c8
-rw-r--r--arch/x86/kernel/smpboot.c28
-rw-r--r--include/asm-x86/apic.h43
-rw-r--r--include/asm-x86/ipi.h16
-rw-r--r--include/asm-x86/paravirt.h2
-rw-r--r--include/asm-x86/smp.h2
9 files changed, 109 insertions, 38 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c
index 3e58b676d23b..2a83c07bd887 100644
--- a/arch/x86/kernel/apic_32.c
+++ b/arch/x86/kernel/apic_32.c
@@ -145,6 +145,12 @@ static int modern_apic(void)
145 return lapic_get_version() >= 0x14; 145 return lapic_get_version() >= 0x14;
146} 146}
147 147
148void apic_icr_write(u32 low, u32 id)
149{
150 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(id));
151 apic_write_around(APIC_ICR, low);
152}
153
148void apic_wait_icr_idle(void) 154void apic_wait_icr_idle(void)
149{ 155{
150 while (apic_read(APIC_ICR) & APIC_ICR_BUSY) 156 while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
index 3963f590c3d4..9bb040689b31 100644
--- a/arch/x86/kernel/apic_64.c
+++ b/arch/x86/kernel/apic_64.c
@@ -119,13 +119,13 @@ static int modern_apic(void)
119 return lapic_get_version() >= 0x14; 119 return lapic_get_version() >= 0x14;
120} 120}
121 121
122void apic_wait_icr_idle(void) 122void xapic_wait_icr_idle(void)
123{ 123{
124 while (apic_read(APIC_ICR) & APIC_ICR_BUSY) 124 while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
125 cpu_relax(); 125 cpu_relax();
126} 126}
127 127
128u32 safe_apic_wait_icr_idle(void) 128u32 safe_xapic_wait_icr_idle(void)
129{ 129{
130 u32 send_status; 130 u32 send_status;
131 int timeout; 131 int timeout;
@@ -141,6 +141,36 @@ u32 safe_apic_wait_icr_idle(void)
141 return send_status; 141 return send_status;
142} 142}
143 143
144void xapic_icr_write(u32 low, u32 id)
145{
146 apic_write(APIC_ICR2, id << 24);
147 apic_write(APIC_ICR, low);
148}
149
150u64 xapic_icr_read(void)
151{
152 u32 icr1, icr2;
153
154 icr2 = apic_read(APIC_ICR2);
155 icr1 = apic_read(APIC_ICR);
156
157 return (icr1 | ((u64)icr2 << 32));
158}
159
160static struct apic_ops xapic_ops = {
161 .read = native_apic_mem_read,
162 .write = native_apic_mem_write,
163 .write_atomic = native_apic_mem_write_atomic,
164 .icr_read = xapic_icr_read,
165 .icr_write = xapic_icr_write,
166 .wait_icr_idle = xapic_wait_icr_idle,
167 .safe_wait_icr_idle = safe_xapic_wait_icr_idle,
168};
169
170struct apic_ops __read_mostly *apic_ops = &xapic_ops;
171
172EXPORT_SYMBOL_GPL(apic_ops);
173
144/** 174/**
145 * enable_NMI_through_LVT0 - enable NMI through local vector table 0 175 * enable_NMI_through_LVT0 - enable NMI through local vector table 0
146 */ 176 */
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index 84dd63c13d63..b62d42ef9283 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -1157,6 +1157,7 @@ static __apicdebuginit void print_APIC_bitfield (int base)
1157void __apicdebuginit print_local_APIC(void * dummy) 1157void __apicdebuginit print_local_APIC(void * dummy)
1158{ 1158{
1159 unsigned int v, ver, maxlvt; 1159 unsigned int v, ver, maxlvt;
1160 unsigned long icr;
1160 1161
1161 if (apic_verbosity == APIC_QUIET) 1162 if (apic_verbosity == APIC_QUIET)
1162 return; 1163 return;
@@ -1200,10 +1201,9 @@ void __apicdebuginit print_local_APIC(void * dummy)
1200 v = apic_read(APIC_ESR); 1201 v = apic_read(APIC_ESR);
1201 printk(KERN_DEBUG "... APIC ESR: %08x\n", v); 1202 printk(KERN_DEBUG "... APIC ESR: %08x\n", v);
1202 1203
1203 v = apic_read(APIC_ICR); 1204 icr = apic_icr_read();
1204 printk(KERN_DEBUG "... APIC ICR: %08x\n", v); 1205 printk(KERN_DEBUG "... APIC ICR: %08x\n", icr);
1205 v = apic_read(APIC_ICR2); 1206 printk(KERN_DEBUG "... APIC ICR2: %08x\n", icr >> 32);
1206 printk(KERN_DEBUG "... APIC ICR2: %08x\n", v);
1207 1207
1208 v = apic_read(APIC_LVTT); 1208 v = apic_read(APIC_LVTT);
1209 printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); 1209 printk(KERN_DEBUG "... APIC LVTT: %08x\n", v);
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index e0f571d58c19..b80105a0f474 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -360,9 +360,11 @@ struct pv_cpu_ops pv_cpu_ops = {
360 360
361struct pv_apic_ops pv_apic_ops = { 361struct pv_apic_ops pv_apic_ops = {
362#ifdef CONFIG_X86_LOCAL_APIC 362#ifdef CONFIG_X86_LOCAL_APIC
363 .apic_write = native_apic_write, 363#ifnded CONFIG_X86_64
364 .apic_write_atomic = native_apic_write_atomic, 364 .apic_write = native_apic_mem_write,
365 .apic_read = native_apic_read, 365 .apic_write_atomic = native_apic_mem_write_atomic,
366 .apic_read = native_apic_mem_read,
367#endif
366 .setup_boot_clock = setup_boot_APIC_clock, 368 .setup_boot_clock = setup_boot_APIC_clock,
367 .setup_secondary_clock = setup_secondary_APIC_clock, 369 .setup_secondary_clock = setup_secondary_APIC_clock,
368 .startup_ipi_hook = paravirt_nop, 370 .startup_ipi_hook = paravirt_nop,
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index f35c2d8016ac..c55263b3df02 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -123,7 +123,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
123 123
124static atomic_t init_deasserted; 124static atomic_t init_deasserted;
125 125
126static int boot_cpu_logical_apicid;
127 126
128/* representing cpus for which sibling maps can be computed */ 127/* representing cpus for which sibling maps can be computed */
129static cpumask_t cpu_sibling_setup_map; 128static cpumask_t cpu_sibling_setup_map;
@@ -165,6 +164,8 @@ static void unmap_cpu_to_node(int cpu)
165#endif 164#endif
166 165
167#ifdef CONFIG_X86_32 166#ifdef CONFIG_X86_32
167static int boot_cpu_logical_apicid;
168
168u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly = 169u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
169 { [0 ... NR_CPUS-1] = BAD_APICID }; 170 { [0 ... NR_CPUS-1] = BAD_APICID };
170 171
@@ -546,8 +547,7 @@ static inline void __inquire_remote_apic(int apicid)
546 printk(KERN_CONT 547 printk(KERN_CONT
547 "a previous APIC delivery may have failed\n"); 548 "a previous APIC delivery may have failed\n");
548 549
549 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); 550 apic_icr_write(APIC_DM_REMRD | regs[i], apicid);
550 apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
551 551
552 timeout = 0; 552 timeout = 0;
553 do { 553 do {
@@ -579,11 +579,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
579 int maxlvt; 579 int maxlvt;
580 580
581 /* Target chip */ 581 /* Target chip */
582 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
583
584 /* Boot on the stack */ 582 /* Boot on the stack */
585 /* Kick the second */ 583 /* Kick the second */
586 apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL); 584 apic_icr_write(APIC_DM_NMI | APIC_DEST_LOGICAL, logical_apicid);
587 585
588 Dprintk("Waiting for send to finish...\n"); 586 Dprintk("Waiting for send to finish...\n");
589 send_status = safe_apic_wait_icr_idle(); 587 send_status = safe_apic_wait_icr_idle();
@@ -639,13 +637,11 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
639 /* 637 /*
640 * Turn INIT on target chip 638 * Turn INIT on target chip
641 */ 639 */
642 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
643
644 /* 640 /*
645 * Send IPI 641 * Send IPI
646 */ 642 */
647 apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT 643 apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT,
648 | APIC_DM_INIT); 644 phys_apicid);
649 645
650 Dprintk("Waiting for send to finish...\n"); 646 Dprintk("Waiting for send to finish...\n");
651 send_status = safe_apic_wait_icr_idle(); 647 send_status = safe_apic_wait_icr_idle();
@@ -655,10 +651,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
655 Dprintk("Deasserting INIT.\n"); 651 Dprintk("Deasserting INIT.\n");
656 652
657 /* Target chip */ 653 /* Target chip */
658 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
659
660 /* Send IPI */ 654 /* Send IPI */
661 apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); 655 apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid);
662 656
663 Dprintk("Waiting for send to finish...\n"); 657 Dprintk("Waiting for send to finish...\n");
664 send_status = safe_apic_wait_icr_idle(); 658 send_status = safe_apic_wait_icr_idle();
@@ -703,12 +697,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
703 */ 697 */
704 698
705 /* Target chip */ 699 /* Target chip */
706 apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
707
708 /* Boot on the stack */ 700 /* Boot on the stack */
709 /* Kick the second */ 701 /* Kick the second */
710 apic_write_around(APIC_ICR, APIC_DM_STARTUP 702 apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12),
711 | (start_eip >> 12)); 703 phys_apicid);
712 704
713 /* 705 /*
714 * Give the other CPU some time to accept the IPI. 706 * Give the other CPU some time to accept the IPI.
@@ -1147,7 +1139,9 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
1147 * Setup boot CPU information 1139 * Setup boot CPU information
1148 */ 1140 */
1149 smp_store_cpu_info(0); /* Final full version of the data */ 1141 smp_store_cpu_info(0); /* Final full version of the data */
1142#ifdef CONFIG_X86_32
1150 boot_cpu_logical_apicid = logical_smp_processor_id(); 1143 boot_cpu_logical_apicid = logical_smp_processor_id();
1144#endif
1151 current_thread_info()->cpu = 0; /* needed? */ 1145 current_thread_info()->cpu = 0; /* needed? */
1152 set_cpu_sibling_map(0); 1146 set_cpu_sibling_map(0);
1153 1147
diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h
index 4e2c1e517f06..6fda195337c5 100644
--- a/include/asm-x86/apic.h
+++ b/include/asm-x86/apic.h
@@ -47,32 +47,59 @@ extern int disable_apic;
47#ifdef CONFIG_PARAVIRT 47#ifdef CONFIG_PARAVIRT
48#include <asm/paravirt.h> 48#include <asm/paravirt.h>
49#else 49#else
50#define apic_write native_apic_write 50#ifndef CONFIG_X86_64
51#define apic_write_atomic native_apic_write_atomic 51#define apic_write native_apic_mem_write
52#define apic_read native_apic_read 52#define apic_write_atomic native_apic_mem_write_atomic
53#define apic_read native_apic_mem_read
54#endif
53#define setup_boot_clock setup_boot_APIC_clock 55#define setup_boot_clock setup_boot_APIC_clock
54#define setup_secondary_clock setup_secondary_APIC_clock 56#define setup_secondary_clock setup_secondary_APIC_clock
55#endif 57#endif
56 58
57extern int is_vsmp_box(void); 59extern int is_vsmp_box(void);
58 60
59static inline void native_apic_write(unsigned long reg, u32 v) 61static inline void native_apic_mem_write(u32 reg, u32 v)
60{ 62{
61 *((volatile u32 *)(APIC_BASE + reg)) = v; 63 *((volatile u32 *)(APIC_BASE + reg)) = v;
62} 64}
63 65
64static inline void native_apic_write_atomic(unsigned long reg, u32 v) 66static inline void native_apic_mem_write_atomic(u32 reg, u32 v)
65{ 67{
66 (void)xchg((u32 *)(APIC_BASE + reg), v); 68 (void)xchg((u32 *)(APIC_BASE + reg), v);
67} 69}
68 70
69static inline u32 native_apic_read(unsigned long reg) 71static inline u32 native_apic_mem_read(u32 reg)
70{ 72{
71 return *((volatile u32 *)(APIC_BASE + reg)); 73 return *((volatile u32 *)(APIC_BASE + reg));
72} 74}
73 75
76#ifdef CONFIG_X86_32
74extern void apic_wait_icr_idle(void); 77extern void apic_wait_icr_idle(void);
75extern u32 safe_apic_wait_icr_idle(void); 78extern u32 safe_apic_wait_icr_idle(void);
79extern void apic_icr_write(u32 low, u32 id);
80#else
81
82struct apic_ops {
83 u32 (*read)(u32 reg);
84 void (*write)(u32 reg, u32 v);
85 void (*write_atomic)(u32 reg, u32 v);
86 u64 (*icr_read)(void);
87 void (*icr_write)(u32 low, u32 high);
88 void (*wait_icr_idle)(void);
89 u32 (*safe_wait_icr_idle)(void);
90};
91
92extern struct apic_ops *apic_ops;
93
94#define apic_read (apic_ops->read)
95#define apic_write (apic_ops->write)
96#define apic_write_atomic (apic_ops->write_atomic)
97#define apic_icr_read (apic_ops->icr_read)
98#define apic_icr_write (apic_ops->icr_write)
99#define apic_wait_icr_idle (apic_ops->wait_icr_idle)
100#define safe_apic_wait_icr_idle (apic_ops->safe_wait_icr_idle)
101#endif
102
76extern int get_physical_broadcast(void); 103extern int get_physical_broadcast(void);
77 104
78#ifdef CONFIG_X86_GOOD_APIC 105#ifdef CONFIG_X86_GOOD_APIC
@@ -95,7 +122,11 @@ static inline void ack_APIC_irq(void)
95 */ 122 */
96 123
97 /* Docs say use 0 for future compatibility */ 124 /* Docs say use 0 for future compatibility */
125#ifdef CONFIG_X86_32
98 apic_write_around(APIC_EOI, 0); 126 apic_write_around(APIC_EOI, 0);
127#else
128 native_apic_mem_write(APIC_EOI, 0);
129#endif
99} 130}
100 131
101extern int lapic_get_maxlvt(void); 132extern int lapic_get_maxlvt(void);
diff --git a/include/asm-x86/ipi.h b/include/asm-x86/ipi.h
index 196d63c28aa4..3d8d6a6c1f8e 100644
--- a/include/asm-x86/ipi.h
+++ b/include/asm-x86/ipi.h
@@ -49,6 +49,12 @@ static inline int __prepare_ICR2(unsigned int mask)
49 return SET_APIC_DEST_FIELD(mask); 49 return SET_APIC_DEST_FIELD(mask);
50} 50}
51 51
52static inline void __xapic_wait_icr_idle(void)
53{
54 while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY)
55 cpu_relax();
56}
57
52static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, 58static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
53 unsigned int dest) 59 unsigned int dest)
54{ 60{
@@ -64,7 +70,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
64 /* 70 /*
65 * Wait for idle. 71 * Wait for idle.
66 */ 72 */
67 apic_wait_icr_idle(); 73 __xapic_wait_icr_idle();
68 74
69 /* 75 /*
70 * No need to touch the target chip field 76 * No need to touch the target chip field
@@ -74,7 +80,7 @@ static inline void __send_IPI_shortcut(unsigned int shortcut, int vector,
74 /* 80 /*
75 * Send the IPI. The write to APIC_ICR fires this off. 81 * Send the IPI. The write to APIC_ICR fires this off.
76 */ 82 */
77 apic_write(APIC_ICR, cfg); 83 native_apic_mem_write(APIC_ICR, cfg);
78} 84}
79 85
80/* 86/*
@@ -92,13 +98,13 @@ static inline void __send_IPI_dest_field(unsigned int mask, int vector,
92 if (unlikely(vector == NMI_VECTOR)) 98 if (unlikely(vector == NMI_VECTOR))
93 safe_apic_wait_icr_idle(); 99 safe_apic_wait_icr_idle();
94 else 100 else
95 apic_wait_icr_idle(); 101 __xapic_wait_icr_idle();
96 102
97 /* 103 /*
98 * prepare target chip field 104 * prepare target chip field
99 */ 105 */
100 cfg = __prepare_ICR2(mask); 106 cfg = __prepare_ICR2(mask);
101 apic_write(APIC_ICR2, cfg); 107 native_apic_mem_write(APIC_ICR2, cfg);
102 108
103 /* 109 /*
104 * program the ICR 110 * program the ICR
@@ -108,7 +114,7 @@ static inline void __send_IPI_dest_field(unsigned int mask, int vector,
108 /* 114 /*
109 * Send the IPI. The write to APIC_ICR fires this off. 115 * Send the IPI. The write to APIC_ICR fires this off.
110 */ 116 */
111 apic_write(APIC_ICR, cfg); 117 native_apic_mem_write(APIC_ICR, cfg);
112} 118}
113 119
114static inline void send_IPI_mask_sequence(cpumask_t mask, int vector) 120static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index ef5e8ec6a6ab..10adac02e6db 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -891,6 +891,7 @@ static inline void slow_down_io(void)
891/* 891/*
892 * Basic functions accessing APICs. 892 * Basic functions accessing APICs.
893 */ 893 */
894#ifndef CONFIG_X86_64
894static inline void apic_write(unsigned long reg, u32 v) 895static inline void apic_write(unsigned long reg, u32 v)
895{ 896{
896 PVOP_VCALL2(pv_apic_ops.apic_write, reg, v); 897 PVOP_VCALL2(pv_apic_ops.apic_write, reg, v);
@@ -905,6 +906,7 @@ static inline u32 apic_read(unsigned long reg)
905{ 906{
906 return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg); 907 return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg);
907} 908}
909#endif
908 910
909static inline void setup_boot_clock(void) 911static inline void setup_boot_clock(void)
910{ 912{
diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h
index 9848715fbd9e..d9d007d22785 100644
--- a/include/asm-x86/smp.h
+++ b/include/asm-x86/smp.h
@@ -158,13 +158,13 @@ extern int safe_smp_processor_id(void);
158 158
159#ifdef CONFIG_X86_LOCAL_APIC 159#ifdef CONFIG_X86_LOCAL_APIC
160 160
161#ifndef CONFIG_X86_64
161static inline int logical_smp_processor_id(void) 162static inline int logical_smp_processor_id(void)
162{ 163{
163 /* we don't want to mark this access volatile - bad code generation */ 164 /* we don't want to mark this access volatile - bad code generation */
164 return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR)); 165 return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
165} 166}
166 167
167#ifndef CONFIG_X86_64
168static inline unsigned int read_apic_id(void) 168static inline unsigned int read_apic_id(void)
169{ 169{
170 return *(u32 *)(APIC_BASE + APIC_ID); 170 return *(u32 *)(APIC_BASE + APIC_ID);