diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2011-11-17 05:00:42 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-11-17 09:25:46 -0500 |
commit | bd59d3a4444e5f941c863db1a7715edf7289e29a (patch) | |
tree | 2e046f944900102b94608984d02d1a20312070e6 /arch/s390 | |
parent | 9e6dabeffd1d0ec2aa19aa076c4886067238d442 (diff) |
KVM: s390: handle SIGP sense running intercepts
SIGP sense running may cause an intercept on higher level
virtualization, so handle it by checking the CPUSTAT_RUNNING flag.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 1 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 39 |
3 files changed, 41 insertions, 0 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 20f9068cd6b5..b0c235cb6ad5 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
@@ -139,6 +139,7 @@ struct kvm_vcpu_stat { | |||
139 | u32 instruction_stfl; | 139 | u32 instruction_stfl; |
140 | u32 instruction_tprot; | 140 | u32 instruction_tprot; |
141 | u32 instruction_sigp_sense; | 141 | u32 instruction_sigp_sense; |
142 | u32 instruction_sigp_sense_running; | ||
142 | u32 instruction_sigp_external_call; | 143 | u32 instruction_sigp_external_call; |
143 | u32 instruction_sigp_emergency; | 144 | u32 instruction_sigp_emergency; |
144 | u32 instruction_sigp_stop; | 145 | u32 instruction_sigp_stop; |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 630ab65b488b..0891926ea953 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -65,6 +65,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
65 | { "instruction_stfl", VCPU_STAT(instruction_stfl) }, | 65 | { "instruction_stfl", VCPU_STAT(instruction_stfl) }, |
66 | { "instruction_tprot", VCPU_STAT(instruction_tprot) }, | 66 | { "instruction_tprot", VCPU_STAT(instruction_tprot) }, |
67 | { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) }, | 67 | { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) }, |
68 | { "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) }, | ||
68 | { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) }, | 69 | { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) }, |
69 | { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) }, | 70 | { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) }, |
70 | { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) }, | 71 | { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) }, |
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 4a488a98d7f8..0a7941d74bc6 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c | |||
@@ -31,9 +31,11 @@ | |||
31 | #define SIGP_SET_PREFIX 0x0d | 31 | #define SIGP_SET_PREFIX 0x0d |
32 | #define SIGP_STORE_STATUS_ADDR 0x0e | 32 | #define SIGP_STORE_STATUS_ADDR 0x0e |
33 | #define SIGP_SET_ARCH 0x12 | 33 | #define SIGP_SET_ARCH 0x12 |
34 | #define SIGP_SENSE_RUNNING 0x15 | ||
34 | 35 | ||
35 | /* cpu status bits */ | 36 | /* cpu status bits */ |
36 | #define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL | 37 | #define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL |
38 | #define SIGP_STAT_NOT_RUNNING 0x00000400UL | ||
37 | #define SIGP_STAT_INCORRECT_STATE 0x00000200UL | 39 | #define SIGP_STAT_INCORRECT_STATE 0x00000200UL |
38 | #define SIGP_STAT_INVALID_PARAMETER 0x00000100UL | 40 | #define SIGP_STAT_INVALID_PARAMETER 0x00000100UL |
39 | #define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL | 41 | #define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL |
@@ -275,6 +277,38 @@ out_fi: | |||
275 | return rc; | 277 | return rc; |
276 | } | 278 | } |
277 | 279 | ||
280 | static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, | ||
281 | unsigned long *reg) | ||
282 | { | ||
283 | int rc; | ||
284 | struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; | ||
285 | |||
286 | if (cpu_addr >= KVM_MAX_VCPUS) | ||
287 | return 3; /* not operational */ | ||
288 | |||
289 | spin_lock(&fi->lock); | ||
290 | if (fi->local_int[cpu_addr] == NULL) | ||
291 | rc = 3; /* not operational */ | ||
292 | else { | ||
293 | if (atomic_read(fi->local_int[cpu_addr]->cpuflags) | ||
294 | & CPUSTAT_RUNNING) { | ||
295 | /* running */ | ||
296 | rc = 1; | ||
297 | } else { | ||
298 | /* not running */ | ||
299 | *reg &= 0xffffffff00000000UL; | ||
300 | *reg |= SIGP_STAT_NOT_RUNNING; | ||
301 | rc = 0; | ||
302 | } | ||
303 | } | ||
304 | spin_unlock(&fi->lock); | ||
305 | |||
306 | VCPU_EVENT(vcpu, 4, "sensed running status of cpu %x rc %x", cpu_addr, | ||
307 | rc); | ||
308 | |||
309 | return rc; | ||
310 | } | ||
311 | |||
278 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | 312 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) |
279 | { | 313 | { |
280 | int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; | 314 | int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; |
@@ -331,6 +365,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | |||
331 | rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, | 365 | rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, |
332 | &vcpu->arch.guest_gprs[r1]); | 366 | &vcpu->arch.guest_gprs[r1]); |
333 | break; | 367 | break; |
368 | case SIGP_SENSE_RUNNING: | ||
369 | vcpu->stat.instruction_sigp_sense_running++; | ||
370 | rc = __sigp_sense_running(vcpu, cpu_addr, | ||
371 | &vcpu->arch.guest_gprs[r1]); | ||
372 | break; | ||
334 | case SIGP_RESTART: | 373 | case SIGP_RESTART: |
335 | vcpu->stat.instruction_sigp_restart++; | 374 | vcpu->stat.instruction_sigp_restart++; |
336 | /* user space must know about restart */ | 375 | /* user space must know about restart */ |