aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Borntraeger <borntraeger@de.ibm.com>2015-07-23 09:24:03 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-10-29 10:59:11 -0400
commit46b708ea875f14f5496109df053624199f3aae87 (patch)
tree53c5d21b613a97aaf98f087f549a3c517fa2a31c
parent58c383c62e1a4379cee531b56e4293211f2d5ded (diff)
KVM: s390: use simple switch statement as multiplexer
We currently do some magic shifting (by exploiting that exit codes are always a multiple of 4) and a table lookup to jump into the exit handlers. This causes some calculations and checks, just to do an potentially expensive function call. Changing that to a switch statement gives the compiler the chance to inline and dynamically decide between jump tables or inline compare and branches. In addition it makes the code more readable. bloat-o-meter gives me a small reduction in code size: add/remove: 0/7 grow/shrink: 1/1 up/down: 986/-1334 (-348) function old new delta kvm_handle_sie_intercept 72 1058 +986 handle_prog 704 696 -8 handle_noop 54 - -54 handle_partial_execution 60 - -60 intercept_funcs 120 - -120 handle_instruction 198 - -198 handle_validity 210 - -210 handle_stop 316 - -316 handle_external_interrupt 368 - -368 Right now my gcc does conditional branches instead of jump tables. The inlining seems to give us enough cycles as some micro-benchmarking shows minimal improvements, but still in noise. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
-rw-r--r--arch/s390/kvm/intercept.c42
1 files changed, 21 insertions, 21 deletions
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 7365e8a46032..b4a5aa110cec 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -336,28 +336,28 @@ static int handle_partial_execution(struct kvm_vcpu *vcpu)
336 return -EOPNOTSUPP; 336 return -EOPNOTSUPP;
337} 337}
338 338
339static const intercept_handler_t intercept_funcs[] = {
340 [0x00 >> 2] = handle_noop,
341 [0x04 >> 2] = handle_instruction,
342 [0x08 >> 2] = handle_prog,
343 [0x10 >> 2] = handle_noop,
344 [0x14 >> 2] = handle_external_interrupt,
345 [0x18 >> 2] = handle_noop,
346 [0x1C >> 2] = kvm_s390_handle_wait,
347 [0x20 >> 2] = handle_validity,
348 [0x28 >> 2] = handle_stop,
349 [0x38 >> 2] = handle_partial_execution,
350};
351
352int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) 339int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
353{ 340{
354 intercept_handler_t func; 341 switch (vcpu->arch.sie_block->icptcode) {
355 u8 code = vcpu->arch.sie_block->icptcode; 342 case 0x00:
356 343 case 0x10:
357 if (code & 3 || (code >> 2) >= ARRAY_SIZE(intercept_funcs)) 344 case 0x18:
345 return handle_noop(vcpu);
346 case 0x04:
347 return handle_instruction(vcpu);
348 case 0x08:
349 return handle_prog(vcpu);
350 case 0x14:
351 return handle_external_interrupt(vcpu);
352 case 0x1c:
353 return kvm_s390_handle_wait(vcpu);
354 case 0x20:
355 return handle_validity(vcpu);
356 case 0x28:
357 return handle_stop(vcpu);
358 case 0x38:
359 return handle_partial_execution(vcpu);
360 default:
358 return -EOPNOTSUPP; 361 return -EOPNOTSUPP;
359 func = intercept_funcs[code >> 2]; 362 }
360 if (func)
361 return func(vcpu);
362 return -EOPNOTSUPP;
363} 363}