aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorHollis Blanchard <hollisb@us.ibm.com>2008-11-05 10:36:23 -0500
committerAvi Kivity <avi@redhat.com>2008-12-31 09:52:23 -0500
commitd4cf3892e50b8e35341086a4fe2bb8a3989b55d4 (patch)
treeadb3275c9d5a2a89605b705434e57e1d0fc48ae6 /arch/powerpc
parent9ab80843c01ac25139e635d018467e528729a317 (diff)
KVM: ppc: optimize irq delivery path
In kvmppc_deliver_interrupt is just one case left in the switch and it is a rare one (less than 8%) when looking at the exit numbers. Therefore we can at least drop the switch/case and if an if. I inserted an unlikely too, but that's open for discussion. In kvmppc_can_deliver_interrupt all frequent cases are in the default case. I know compilers are smart but we can make it easier for them. By writing down all options and removing the default case combined with the fact that ithe values are constants 0..15 should allow the compiler to write an easy jump table. Modifying kvmppc_can_deliver_interrupt pointed me to the fact that gcc seems to be unable to reduce priority_exception[x] to a build time constant. Therefore I changed the usage of the translation arrays in the interrupt delivery path completely. It is now using priority without translation to irq on the full irq delivery path. To be able to do that ivpr regs are stored by their priority now. Additionally the decision made in kvmppc_can_deliver_interrupt is already sufficient to get the value of interrupt_msr_mask[x]. Therefore we can replace the 16x4byte array used here with a single 4byte variable (might still be one miss, but the chance to find this in cache should be better than the right entry of the whole array). Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h3
-rw-r--r--arch/powerpc/kvm/44x_emulate.c100
-rw-r--r--arch/powerpc/kvm/booke.c175
-rw-r--r--arch/powerpc/kvm/booke.h18
4 files changed, 140 insertions, 156 deletions
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 976ecc4b322e..844f683302f6 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -36,9 +36,6 @@ enum emulation_result {
36 EMULATE_FAIL, /* can't emulate this instruction */ 36 EMULATE_FAIL, /* can't emulate this instruction */
37}; 37};
38 38
39extern const unsigned char exception_priority[];
40extern const unsigned char priority_exception[];
41
42extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); 39extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
43extern char kvmppc_handlers_start[]; 40extern char kvmppc_handlers_start[];
44extern unsigned long kvmppc_handler_len; 41extern unsigned long kvmppc_handler_len;
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
index a634c0c4fa7e..9bc50cebf9ec 100644
--- a/arch/powerpc/kvm/44x_emulate.c
+++ b/arch/powerpc/kvm/44x_emulate.c
@@ -228,39 +228,56 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
228 vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break; 228 vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
229 229
230 case SPRN_IVPR: 230 case SPRN_IVPR:
231 vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break; 231 vcpu->arch.ivpr = vcpu->arch.gpr[rs];
232 break;
232 case SPRN_IVOR0: 233 case SPRN_IVOR0:
233 vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break; 234 vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs];
235 break;
234 case SPRN_IVOR1: 236 case SPRN_IVOR1:
235 vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break; 237 vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs];
238 break;
236 case SPRN_IVOR2: 239 case SPRN_IVOR2:
237 vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break; 240 vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs];
241 break;
238 case SPRN_IVOR3: 242 case SPRN_IVOR3:
239 vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break; 243 vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs];
244 break;
240 case SPRN_IVOR4: 245 case SPRN_IVOR4:
241 vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break; 246 vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs];
247 break;
242 case SPRN_IVOR5: 248 case SPRN_IVOR5:
243 vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break; 249 vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs];
250 break;
244 case SPRN_IVOR6: 251 case SPRN_IVOR6:
245 vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break; 252 vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs];
253 break;
246 case SPRN_IVOR7: 254 case SPRN_IVOR7:
247 vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break; 255 vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs];
256 break;
248 case SPRN_IVOR8: 257 case SPRN_IVOR8:
249 vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break; 258 vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs];
259 break;
250 case SPRN_IVOR9: 260 case SPRN_IVOR9:
251 vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break; 261 vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs];
262 break;
252 case SPRN_IVOR10: 263 case SPRN_IVOR10:
253 vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break; 264 vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs];
265 break;
254 case SPRN_IVOR11: 266 case SPRN_IVOR11:
255 vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break; 267 vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs];
268 break;
256 case SPRN_IVOR12: 269 case SPRN_IVOR12:
257 vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break; 270 vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs];
271 break;
258 case SPRN_IVOR13: 272 case SPRN_IVOR13:
259 vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break; 273 vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs];
274 break;
260 case SPRN_IVOR14: 275 case SPRN_IVOR14:
261 vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break; 276 vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs];
277 break;
262 case SPRN_IVOR15: 278 case SPRN_IVOR15:
263 vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break; 279 vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs];
280 break;
264 281
265 default: 282 default:
266 return EMULATE_FAIL; 283 return EMULATE_FAIL;
@@ -295,37 +312,54 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
295 vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break; 312 vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
296 313
297 case SPRN_IVOR0: 314 case SPRN_IVOR0:
298 vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break; 315 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL];
316 break;
299 case SPRN_IVOR1: 317 case SPRN_IVOR1:
300 vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break; 318 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK];
319 break;
301 case SPRN_IVOR2: 320 case SPRN_IVOR2:
302 vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break; 321 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE];
322 break;
303 case SPRN_IVOR3: 323 case SPRN_IVOR3:
304 vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break; 324 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE];
325 break;
305 case SPRN_IVOR4: 326 case SPRN_IVOR4:
306 vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break; 327 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL];
328 break;
307 case SPRN_IVOR5: 329 case SPRN_IVOR5:
308 vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break; 330 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT];
331 break;
309 case SPRN_IVOR6: 332 case SPRN_IVOR6:
310 vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break; 333 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM];
334 break;
311 case SPRN_IVOR7: 335 case SPRN_IVOR7:
312 vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break; 336 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL];
337 break;
313 case SPRN_IVOR8: 338 case SPRN_IVOR8:
314 vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break; 339 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL];
340 break;
315 case SPRN_IVOR9: 341 case SPRN_IVOR9:
316 vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break; 342 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL];
343 break;
317 case SPRN_IVOR10: 344 case SPRN_IVOR10:
318 vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break; 345 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER];
346 break;
319 case SPRN_IVOR11: 347 case SPRN_IVOR11:
320 vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break; 348 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT];
349 break;
321 case SPRN_IVOR12: 350 case SPRN_IVOR12:
322 vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break; 351 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG];
352 break;
323 case SPRN_IVOR13: 353 case SPRN_IVOR13:
324 vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break; 354 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS];
355 break;
325 case SPRN_IVOR14: 356 case SPRN_IVOR14:
326 vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break; 357 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS];
358 break;
327 case SPRN_IVOR15: 359 case SPRN_IVOR15:
328 vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break; 360 vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
361 break;
362
329 default: 363 default:
330 return EMULATE_FAIL; 364 return EMULATE_FAIL;
331 } 365 }
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 0f064719162c..ec59a6768ec3 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -55,64 +55,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
55 { NULL } 55 { NULL }
56}; 56};
57 57
58static const u32 interrupt_msr_mask[16] = {
59 [BOOKE_INTERRUPT_CRITICAL] = MSR_ME,
60 [BOOKE_INTERRUPT_MACHINE_CHECK] = 0,
61 [BOOKE_INTERRUPT_DATA_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
62 [BOOKE_INTERRUPT_INST_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
63 [BOOKE_INTERRUPT_EXTERNAL] = MSR_CE|MSR_ME|MSR_DE,
64 [BOOKE_INTERRUPT_ALIGNMENT] = MSR_CE|MSR_ME|MSR_DE,
65 [BOOKE_INTERRUPT_PROGRAM] = MSR_CE|MSR_ME|MSR_DE,
66 [BOOKE_INTERRUPT_FP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
67 [BOOKE_INTERRUPT_SYSCALL] = MSR_CE|MSR_ME|MSR_DE,
68 [BOOKE_INTERRUPT_AP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
69 [BOOKE_INTERRUPT_DECREMENTER] = MSR_CE|MSR_ME|MSR_DE,
70 [BOOKE_INTERRUPT_FIT] = MSR_CE|MSR_ME|MSR_DE,
71 [BOOKE_INTERRUPT_WATCHDOG] = MSR_ME,
72 [BOOKE_INTERRUPT_DTLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
73 [BOOKE_INTERRUPT_ITLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
74 [BOOKE_INTERRUPT_DEBUG] = MSR_ME,
75};
76
77const unsigned char exception_priority[] = {
78 [BOOKE_INTERRUPT_DATA_STORAGE] = 0,
79 [BOOKE_INTERRUPT_INST_STORAGE] = 1,
80 [BOOKE_INTERRUPT_ALIGNMENT] = 2,
81 [BOOKE_INTERRUPT_PROGRAM] = 3,
82 [BOOKE_INTERRUPT_FP_UNAVAIL] = 4,
83 [BOOKE_INTERRUPT_SYSCALL] = 5,
84 [BOOKE_INTERRUPT_AP_UNAVAIL] = 6,
85 [BOOKE_INTERRUPT_DTLB_MISS] = 7,
86 [BOOKE_INTERRUPT_ITLB_MISS] = 8,
87 [BOOKE_INTERRUPT_MACHINE_CHECK] = 9,
88 [BOOKE_INTERRUPT_DEBUG] = 10,
89 [BOOKE_INTERRUPT_CRITICAL] = 11,
90 [BOOKE_INTERRUPT_WATCHDOG] = 12,
91 [BOOKE_INTERRUPT_EXTERNAL] = 13,
92 [BOOKE_INTERRUPT_FIT] = 14,
93 [BOOKE_INTERRUPT_DECREMENTER] = 15,
94};
95
96const unsigned char priority_exception[] = {
97 BOOKE_INTERRUPT_DATA_STORAGE,
98 BOOKE_INTERRUPT_INST_STORAGE,
99 BOOKE_INTERRUPT_ALIGNMENT,
100 BOOKE_INTERRUPT_PROGRAM,
101 BOOKE_INTERRUPT_FP_UNAVAIL,
102 BOOKE_INTERRUPT_SYSCALL,
103 BOOKE_INTERRUPT_AP_UNAVAIL,
104 BOOKE_INTERRUPT_DTLB_MISS,
105 BOOKE_INTERRUPT_ITLB_MISS,
106 BOOKE_INTERRUPT_MACHINE_CHECK,
107 BOOKE_INTERRUPT_DEBUG,
108 BOOKE_INTERRUPT_CRITICAL,
109 BOOKE_INTERRUPT_WATCHDOG,
110 BOOKE_INTERRUPT_EXTERNAL,
111 BOOKE_INTERRUPT_FIT,
112 BOOKE_INTERRUPT_DECREMENTER,
113};
114
115
116/* TODO: use vcpu_printf() */ 58/* TODO: use vcpu_printf() */
117void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu) 59void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
118{ 60{
@@ -133,103 +75,96 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
133 } 75 }
134} 76}
135 77
136static void kvmppc_booke_queue_exception(struct kvm_vcpu *vcpu, int exception) 78static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
79 unsigned int priority)
137{ 80{
138 unsigned int priority = exception_priority[exception];
139 set_bit(priority, &vcpu->arch.pending_exceptions); 81 set_bit(priority, &vcpu->arch.pending_exceptions);
140} 82}
141 83
142static void kvmppc_booke_clear_exception(struct kvm_vcpu *vcpu, int exception)
143{
144 unsigned int priority = exception_priority[exception];
145 clear_bit(priority, &vcpu->arch.pending_exceptions);
146}
147
148void kvmppc_core_queue_program(struct kvm_vcpu *vcpu) 84void kvmppc_core_queue_program(struct kvm_vcpu *vcpu)
149{ 85{
150 kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); 86 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
151} 87}
152 88
153void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu) 89void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
154{ 90{
155 kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER); 91 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DECREMENTER);
156} 92}
157 93
158int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu) 94int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
159{ 95{
160 unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER]; 96 return test_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
161 return test_bit(priority, &vcpu->arch.pending_exceptions);
162} 97}
163 98
164void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, 99void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
165 struct kvm_interrupt *irq) 100 struct kvm_interrupt *irq)
166{ 101{
167 kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL); 102 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_EXTERNAL);
168} 103}
169 104
170/* Check if we are ready to deliver the interrupt */ 105/* Deliver the interrupt of the corresponding priority, if possible. */
171static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) 106static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
107 unsigned int priority)
172{ 108{
173 int r; 109 int allowed = 0;
174 110 ulong msr_mask;
175 switch (interrupt) { 111
176 case BOOKE_INTERRUPT_CRITICAL: 112 switch (priority) {
177 r = vcpu->arch.msr & MSR_CE; 113 case BOOKE_IRQPRIO_PROGRAM:
114 case BOOKE_IRQPRIO_DTLB_MISS:
115 case BOOKE_IRQPRIO_ITLB_MISS:
116 case BOOKE_IRQPRIO_SYSCALL:
117 case BOOKE_IRQPRIO_DATA_STORAGE:
118 case BOOKE_IRQPRIO_INST_STORAGE:
119 case BOOKE_IRQPRIO_FP_UNAVAIL:
120 case BOOKE_IRQPRIO_AP_UNAVAIL:
121 case BOOKE_IRQPRIO_ALIGNMENT:
122 allowed = 1;
123 msr_mask = MSR_CE|MSR_ME|MSR_DE;
178 break; 124 break;
179 case BOOKE_INTERRUPT_MACHINE_CHECK: 125 case BOOKE_IRQPRIO_CRITICAL:
180 r = vcpu->arch.msr & MSR_ME; 126 case BOOKE_IRQPRIO_WATCHDOG:
127 allowed = vcpu->arch.msr & MSR_CE;
128 msr_mask = MSR_ME;
181 break; 129 break;
182 case BOOKE_INTERRUPT_EXTERNAL: 130 case BOOKE_IRQPRIO_MACHINE_CHECK:
183 r = vcpu->arch.msr & MSR_EE; 131 allowed = vcpu->arch.msr & MSR_ME;
184 break; 132 msr_mask = 0;
185 case BOOKE_INTERRUPT_DECREMENTER:
186 r = vcpu->arch.msr & MSR_EE;
187 break; 133 break;
188 case BOOKE_INTERRUPT_FIT: 134 case BOOKE_IRQPRIO_EXTERNAL:
189 r = vcpu->arch.msr & MSR_EE; 135 case BOOKE_IRQPRIO_DECREMENTER:
136 case BOOKE_IRQPRIO_FIT:
137 allowed = vcpu->arch.msr & MSR_EE;
138 msr_mask = MSR_CE|MSR_ME|MSR_DE;
190 break; 139 break;
191 case BOOKE_INTERRUPT_WATCHDOG: 140 case BOOKE_IRQPRIO_DEBUG:
192 r = vcpu->arch.msr & MSR_CE; 141 allowed = vcpu->arch.msr & MSR_DE;
142 msr_mask = MSR_ME;
193 break; 143 break;
194 case BOOKE_INTERRUPT_DEBUG:
195 r = vcpu->arch.msr & MSR_DE;
196 break;
197 default:
198 r = 1;
199 } 144 }
200 145
201 return r; 146 if (allowed) {
202} 147 vcpu->arch.srr0 = vcpu->arch.pc;
148 vcpu->arch.srr1 = vcpu->arch.msr;
149 vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
150 kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask);
203 151
204static void kvmppc_booke_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) 152 clear_bit(priority, &vcpu->arch.pending_exceptions);
205{
206 switch (interrupt) {
207 case BOOKE_INTERRUPT_DECREMENTER:
208 vcpu->arch.tsr |= TSR_DIS;
209 break;
210 } 153 }
211 154
212 vcpu->arch.srr0 = vcpu->arch.pc; 155 return allowed;
213 vcpu->arch.srr1 = vcpu->arch.msr;
214 vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[interrupt];
215 kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[interrupt]);
216} 156}
217 157
218/* Check pending exceptions and deliver one, if possible. */ 158/* Check pending exceptions and deliver one, if possible. */
219void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) 159void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
220{ 160{
221 unsigned long *pending = &vcpu->arch.pending_exceptions; 161 unsigned long *pending = &vcpu->arch.pending_exceptions;
222 unsigned int exception;
223 unsigned int priority; 162 unsigned int priority;
224 163
225 priority = __ffs(*pending); 164 priority = __ffs(*pending);
226 while (priority <= BOOKE_MAX_INTERRUPT) { 165 while (priority <= BOOKE_MAX_INTERRUPT) {
227 exception = priority_exception[priority]; 166 if (kvmppc_booke_irqprio_deliver(vcpu, priority))
228 if (kvmppc_can_deliver_interrupt(vcpu, exception)) {
229 kvmppc_booke_clear_exception(vcpu, exception);
230 kvmppc_booke_deliver_interrupt(vcpu, exception);
231 break; 167 break;
232 }
233 168
234 priority = find_next_bit(pending, 169 priority = find_next_bit(pending,
235 BITS_PER_BYTE * sizeof(*pending), 170 BITS_PER_BYTE * sizeof(*pending),
@@ -287,7 +222,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
287 /* Program traps generated by user-level software must be handled 222 /* Program traps generated by user-level software must be handled
288 * by the guest kernel. */ 223 * by the guest kernel. */
289 vcpu->arch.esr = vcpu->arch.fault_esr; 224 vcpu->arch.esr = vcpu->arch.fault_esr;
290 kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); 225 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
291 r = RESUME_GUEST; 226 r = RESUME_GUEST;
292 break; 227 break;
293 } 228 }
@@ -321,27 +256,27 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
321 break; 256 break;
322 257
323 case BOOKE_INTERRUPT_FP_UNAVAIL: 258 case BOOKE_INTERRUPT_FP_UNAVAIL:
324 kvmppc_booke_queue_exception(vcpu, exit_nr); 259 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_FP_UNAVAIL);
325 r = RESUME_GUEST; 260 r = RESUME_GUEST;
326 break; 261 break;
327 262
328 case BOOKE_INTERRUPT_DATA_STORAGE: 263 case BOOKE_INTERRUPT_DATA_STORAGE:
329 vcpu->arch.dear = vcpu->arch.fault_dear; 264 vcpu->arch.dear = vcpu->arch.fault_dear;
330 vcpu->arch.esr = vcpu->arch.fault_esr; 265 vcpu->arch.esr = vcpu->arch.fault_esr;
331 kvmppc_booke_queue_exception(vcpu, exit_nr); 266 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE);
332 vcpu->stat.dsi_exits++; 267 vcpu->stat.dsi_exits++;
333 r = RESUME_GUEST; 268 r = RESUME_GUEST;
334 break; 269 break;
335 270
336 case BOOKE_INTERRUPT_INST_STORAGE: 271 case BOOKE_INTERRUPT_INST_STORAGE:
337 vcpu->arch.esr = vcpu->arch.fault_esr; 272 vcpu->arch.esr = vcpu->arch.fault_esr;
338 kvmppc_booke_queue_exception(vcpu, exit_nr); 273 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
339 vcpu->stat.isi_exits++; 274 vcpu->stat.isi_exits++;
340 r = RESUME_GUEST; 275 r = RESUME_GUEST;
341 break; 276 break;
342 277
343 case BOOKE_INTERRUPT_SYSCALL: 278 case BOOKE_INTERRUPT_SYSCALL:
344 kvmppc_booke_queue_exception(vcpu, exit_nr); 279 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SYSCALL);
345 vcpu->stat.syscall_exits++; 280 vcpu->stat.syscall_exits++;
346 r = RESUME_GUEST; 281 r = RESUME_GUEST;
347 break; 282 break;
@@ -355,7 +290,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
355 gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr); 290 gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr);
356 if (!gtlbe) { 291 if (!gtlbe) {
357 /* The guest didn't have a mapping for it. */ 292 /* The guest didn't have a mapping for it. */
358 kvmppc_booke_queue_exception(vcpu, exit_nr); 293 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
359 vcpu->arch.dear = vcpu->arch.fault_dear; 294 vcpu->arch.dear = vcpu->arch.fault_dear;
360 vcpu->arch.esr = vcpu->arch.fault_esr; 295 vcpu->arch.esr = vcpu->arch.fault_esr;
361 vcpu->stat.dtlb_real_miss_exits++; 296 vcpu->stat.dtlb_real_miss_exits++;
@@ -398,7 +333,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
398 gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr); 333 gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr);
399 if (!gtlbe) { 334 if (!gtlbe) {
400 /* The guest didn't have a mapping for it. */ 335 /* The guest didn't have a mapping for it. */
401 kvmppc_booke_queue_exception(vcpu, exit_nr); 336 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS);
402 vcpu->stat.itlb_real_miss_exits++; 337 vcpu->stat.itlb_real_miss_exits++;
403 break; 338 break;
404 } 339 }
@@ -418,7 +353,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
418 gtlbe->word2); 353 gtlbe->word2);
419 } else { 354 } else {
420 /* Guest mapped and leaped at non-RAM! */ 355 /* Guest mapped and leaped at non-RAM! */
421 kvmppc_booke_queue_exception(vcpu, BOOKE_INTERRUPT_MACHINE_CHECK); 356 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK);
422 } 357 }
423 358
424 break; 359 break;
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
index f694a4b2dafa..48d905fd60ab 100644
--- a/arch/powerpc/kvm/booke.h
+++ b/arch/powerpc/kvm/booke.h
@@ -23,6 +23,24 @@
23#include <linux/types.h> 23#include <linux/types.h>
24#include <linux/kvm_host.h> 24#include <linux/kvm_host.h>
25 25
26/* interrupt priortity ordering */
27#define BOOKE_IRQPRIO_DATA_STORAGE 0
28#define BOOKE_IRQPRIO_INST_STORAGE 1
29#define BOOKE_IRQPRIO_ALIGNMENT 2
30#define BOOKE_IRQPRIO_PROGRAM 3
31#define BOOKE_IRQPRIO_FP_UNAVAIL 4
32#define BOOKE_IRQPRIO_SYSCALL 5
33#define BOOKE_IRQPRIO_AP_UNAVAIL 6
34#define BOOKE_IRQPRIO_DTLB_MISS 7
35#define BOOKE_IRQPRIO_ITLB_MISS 8
36#define BOOKE_IRQPRIO_MACHINE_CHECK 9
37#define BOOKE_IRQPRIO_DEBUG 10
38#define BOOKE_IRQPRIO_CRITICAL 11
39#define BOOKE_IRQPRIO_WATCHDOG 12
40#define BOOKE_IRQPRIO_EXTERNAL 13
41#define BOOKE_IRQPRIO_FIT 14
42#define BOOKE_IRQPRIO_DECREMENTER 15
43
26/* Helper function for "full" MSR writes. No need to call this if only EE is 44/* Helper function for "full" MSR writes. No need to call this if only EE is
27 * changing. */ 45 * changing. */
28static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) 46static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)