diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2015-07-23 09:24:03 -0400 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2015-10-29 10:59:11 -0400 |
commit | 46b708ea875f14f5496109df053624199f3aae87 (patch) | |
tree | 53c5d21b613a97aaf98f087f549a3c517fa2a31c | |
parent | 58c383c62e1a4379cee531b56e4293211f2d5ded (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.c | 42 |
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 | ||
339 | static 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 | |||
352 | int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) | 339 | int 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 | } |