Skip to content

Commit 722c2cd

Browse files
committed
Merge tag 'kvm-s390-master-4.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD
KVM: s390: Fixes and improvements for 4.16 - optimization for the exitless interrupt support that was merged in 4.16-rc1 - improve the branch prediction blocking for nested KVM - replace some jump tables with switch statements to improve expoline performance
2 parents 7928b2c + baabee6 commit 722c2cd

File tree

5 files changed

+200
-154
lines changed

5 files changed

+200
-154
lines changed

arch/s390/kvm/intercept.c

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,6 @@
2222
#include "trace.h"
2323
#include "trace-s390.h"
2424

25-
26-
static const intercept_handler_t instruction_handlers[256] = {
27-
[0x01] = kvm_s390_handle_01,
28-
[0x82] = kvm_s390_handle_lpsw,
29-
[0x83] = kvm_s390_handle_diag,
30-
[0xaa] = kvm_s390_handle_aa,
31-
[0xae] = kvm_s390_handle_sigp,
32-
[0xb2] = kvm_s390_handle_b2,
33-
[0xb6] = kvm_s390_handle_stctl,
34-
[0xb7] = kvm_s390_handle_lctl,
35-
[0xb9] = kvm_s390_handle_b9,
36-
[0xe3] = kvm_s390_handle_e3,
37-
[0xe5] = kvm_s390_handle_e5,
38-
[0xeb] = kvm_s390_handle_eb,
39-
};
40-
4125
u8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu)
4226
{
4327
struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
@@ -129,16 +113,39 @@ static int handle_validity(struct kvm_vcpu *vcpu)
129113

130114
static int handle_instruction(struct kvm_vcpu *vcpu)
131115
{
132-
intercept_handler_t handler;
133-
134116
vcpu->stat.exit_instruction++;
135117
trace_kvm_s390_intercept_instruction(vcpu,
136118
vcpu->arch.sie_block->ipa,
137119
vcpu->arch.sie_block->ipb);
138-
handler = instruction_handlers[vcpu->arch.sie_block->ipa >> 8];
139-
if (handler)
140-
return handler(vcpu);
141-
return -EOPNOTSUPP;
120+
121+
switch (vcpu->arch.sie_block->ipa >> 8) {
122+
case 0x01:
123+
return kvm_s390_handle_01(vcpu);
124+
case 0x82:
125+
return kvm_s390_handle_lpsw(vcpu);
126+
case 0x83:
127+
return kvm_s390_handle_diag(vcpu);
128+
case 0xaa:
129+
return kvm_s390_handle_aa(vcpu);
130+
case 0xae:
131+
return kvm_s390_handle_sigp(vcpu);
132+
case 0xb2:
133+
return kvm_s390_handle_b2(vcpu);
134+
case 0xb6:
135+
return kvm_s390_handle_stctl(vcpu);
136+
case 0xb7:
137+
return kvm_s390_handle_lctl(vcpu);
138+
case 0xb9:
139+
return kvm_s390_handle_b9(vcpu);
140+
case 0xe3:
141+
return kvm_s390_handle_e3(vcpu);
142+
case 0xe5:
143+
return kvm_s390_handle_e5(vcpu);
144+
case 0xeb:
145+
return kvm_s390_handle_eb(vcpu);
146+
default:
147+
return -EOPNOTSUPP;
148+
}
142149
}
143150

144151
static int inject_prog_on_prog_intercept(struct kvm_vcpu *vcpu)

arch/s390/kvm/interrupt.c

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,6 @@ static int cpu_timer_irq_pending(struct kvm_vcpu *vcpu)
187187
return kvm_s390_get_cpu_timer(vcpu) >> 63;
188188
}
189189

190-
static inline int is_ioirq(unsigned long irq_type)
191-
{
192-
return ((irq_type >= IRQ_PEND_IO_ISC_7) &&
193-
(irq_type <= IRQ_PEND_IO_ISC_0));
194-
}
195-
196190
static uint64_t isc_to_isc_bits(int isc)
197191
{
198192
return (0x80 >> isc) << 24;
@@ -236,10 +230,15 @@ static inline int kvm_s390_gisa_tac_ipm_gisc(struct kvm_s390_gisa *gisa, u32 gis
236230
return test_and_clear_bit_inv(IPM_BIT_OFFSET + gisc, (unsigned long *) gisa);
237231
}
238232

239-
static inline unsigned long pending_irqs(struct kvm_vcpu *vcpu)
233+
static inline unsigned long pending_irqs_no_gisa(struct kvm_vcpu *vcpu)
240234
{
241235
return vcpu->kvm->arch.float_int.pending_irqs |
242-
vcpu->arch.local_int.pending_irqs |
236+
vcpu->arch.local_int.pending_irqs;
237+
}
238+
239+
static inline unsigned long pending_irqs(struct kvm_vcpu *vcpu)
240+
{
241+
return pending_irqs_no_gisa(vcpu) |
243242
kvm_s390_gisa_get_ipm(vcpu->kvm->arch.gisa) << IRQ_PEND_IO_ISC_7;
244243
}
245244

@@ -337,7 +336,7 @@ static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
337336

338337
static void set_intercept_indicators_io(struct kvm_vcpu *vcpu)
339338
{
340-
if (!(pending_irqs(vcpu) & IRQ_PEND_IO_MASK))
339+
if (!(pending_irqs_no_gisa(vcpu) & IRQ_PEND_IO_MASK))
341340
return;
342341
else if (psw_ioint_disabled(vcpu))
343342
kvm_s390_set_cpuflags(vcpu, CPUSTAT_IO_INT);
@@ -1011,24 +1010,6 @@ static int __must_check __deliver_io(struct kvm_vcpu *vcpu,
10111010
return rc;
10121011
}
10131012

1014-
typedef int (*deliver_irq_t)(struct kvm_vcpu *vcpu);
1015-
1016-
static const deliver_irq_t deliver_irq_funcs[] = {
1017-
[IRQ_PEND_MCHK_EX] = __deliver_machine_check,
1018-
[IRQ_PEND_MCHK_REP] = __deliver_machine_check,
1019-
[IRQ_PEND_PROG] = __deliver_prog,
1020-
[IRQ_PEND_EXT_EMERGENCY] = __deliver_emergency_signal,
1021-
[IRQ_PEND_EXT_EXTERNAL] = __deliver_external_call,
1022-
[IRQ_PEND_EXT_CLOCK_COMP] = __deliver_ckc,
1023-
[IRQ_PEND_EXT_CPU_TIMER] = __deliver_cpu_timer,
1024-
[IRQ_PEND_RESTART] = __deliver_restart,
1025-
[IRQ_PEND_SET_PREFIX] = __deliver_set_prefix,
1026-
[IRQ_PEND_PFAULT_INIT] = __deliver_pfault_init,
1027-
[IRQ_PEND_EXT_SERVICE] = __deliver_service,
1028-
[IRQ_PEND_PFAULT_DONE] = __deliver_pfault_done,
1029-
[IRQ_PEND_VIRTIO] = __deliver_virtio,
1030-
};
1031-
10321013
/* Check whether an external call is pending (deliverable or not) */
10331014
int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu)
10341015
{
@@ -1192,7 +1173,6 @@ void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu)
11921173
int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
11931174
{
11941175
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
1195-
deliver_irq_t func;
11961176
int rc = 0;
11971177
unsigned long irq_type;
11981178
unsigned long irqs;
@@ -1212,16 +1192,57 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
12121192
while ((irqs = deliverable_irqs(vcpu)) && !rc) {
12131193
/* bits are in the reverse order of interrupt priority */
12141194
irq_type = find_last_bit(&irqs, IRQ_PEND_COUNT);
1215-
if (is_ioirq(irq_type)) {
1195+
switch (irq_type) {
1196+
case IRQ_PEND_IO_ISC_0:
1197+
case IRQ_PEND_IO_ISC_1:
1198+
case IRQ_PEND_IO_ISC_2:
1199+
case IRQ_PEND_IO_ISC_3:
1200+
case IRQ_PEND_IO_ISC_4:
1201+
case IRQ_PEND_IO_ISC_5:
1202+
case IRQ_PEND_IO_ISC_6:
1203+
case IRQ_PEND_IO_ISC_7:
12161204
rc = __deliver_io(vcpu, irq_type);
1217-
} else {
1218-
func = deliver_irq_funcs[irq_type];
1219-
if (!func) {
1220-
WARN_ON_ONCE(func == NULL);
1221-
clear_bit(irq_type, &li->pending_irqs);
1222-
continue;
1223-
}
1224-
rc = func(vcpu);
1205+
break;
1206+
case IRQ_PEND_MCHK_EX:
1207+
case IRQ_PEND_MCHK_REP:
1208+
rc = __deliver_machine_check(vcpu);
1209+
break;
1210+
case IRQ_PEND_PROG:
1211+
rc = __deliver_prog(vcpu);
1212+
break;
1213+
case IRQ_PEND_EXT_EMERGENCY:
1214+
rc = __deliver_emergency_signal(vcpu);
1215+
break;
1216+
case IRQ_PEND_EXT_EXTERNAL:
1217+
rc = __deliver_external_call(vcpu);
1218+
break;
1219+
case IRQ_PEND_EXT_CLOCK_COMP:
1220+
rc = __deliver_ckc(vcpu);
1221+
break;
1222+
case IRQ_PEND_EXT_CPU_TIMER:
1223+
rc = __deliver_cpu_timer(vcpu);
1224+
break;
1225+
case IRQ_PEND_RESTART:
1226+
rc = __deliver_restart(vcpu);
1227+
break;
1228+
case IRQ_PEND_SET_PREFIX:
1229+
rc = __deliver_set_prefix(vcpu);
1230+
break;
1231+
case IRQ_PEND_PFAULT_INIT:
1232+
rc = __deliver_pfault_init(vcpu);
1233+
break;
1234+
case IRQ_PEND_EXT_SERVICE:
1235+
rc = __deliver_service(vcpu);
1236+
break;
1237+
case IRQ_PEND_PFAULT_DONE:
1238+
rc = __deliver_pfault_done(vcpu);
1239+
break;
1240+
case IRQ_PEND_VIRTIO:
1241+
rc = __deliver_virtio(vcpu);
1242+
break;
1243+
default:
1244+
WARN_ONCE(1, "Unknown pending irq type %ld", irq_type);
1245+
clear_bit(irq_type, &li->pending_irqs);
12251246
}
12261247
}
12271248

@@ -1701,7 +1722,8 @@ static void __floating_irq_kick(struct kvm *kvm, u64 type)
17011722
kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_STOP_INT);
17021723
break;
17031724
case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
1704-
kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_IO_INT);
1725+
if (!(type & KVM_S390_INT_IO_AI_MASK && kvm->arch.gisa))
1726+
kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_IO_INT);
17051727
break;
17061728
default:
17071729
kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_EXT_INT);

arch/s390/kvm/kvm-s390.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
#include <asm/processor.h>
2020
#include <asm/sclp.h>
2121

22-
typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
23-
2422
/* Transactional Memory Execution related macros */
2523
#define IS_TE_ENABLED(vcpu) ((vcpu->arch.sie_block->ecb & ECB_TE))
2624
#define TDB_FORMAT1 1

0 commit comments

Comments
 (0)