diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-12-12 05:41:33 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-12-12 05:41:33 -0500 |
commit | 6bb05ef78553491b2e2e0710dde364331dc3cdd2 (patch) | |
tree | 02e15152f1fa25c21155d1e021d20972ac57ea36 /arch/s390 | |
parent | 6dfacadd5858882eee1983995854d4e1fb1b966e (diff) | |
parent | ff1f3cb4b3ac5d039f02679f34cb1498d110d241 (diff) |
Merge tag 'kvm-s390-20131211' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into kvm-next
Some further s390 patches for kvm-next.
Various improvements and bugfixes in the signal processor handling.
Document kvm support for diagnose (s390 hypercalls). And last but
not least, fix a bug in the s390 ioeventfd backend that was causing
us grief in scenarios with 4G+ memory.
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/include/asm/sigp.h | 2 | ||||
-rw-r--r-- | arch/s390/kvm/diag.c | 2 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 64 |
3 files changed, 56 insertions, 12 deletions
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h index 5a87d16d3e7c..d091aa1aaf11 100644 --- a/arch/s390/include/asm/sigp.h +++ b/arch/s390/include/asm/sigp.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #define SIGP_SENSE 1 | 5 | #define SIGP_SENSE 1 |
6 | #define SIGP_EXTERNAL_CALL 2 | 6 | #define SIGP_EXTERNAL_CALL 2 |
7 | #define SIGP_EMERGENCY_SIGNAL 3 | 7 | #define SIGP_EMERGENCY_SIGNAL 3 |
8 | #define SIGP_START 4 | ||
8 | #define SIGP_STOP 5 | 9 | #define SIGP_STOP 5 |
9 | #define SIGP_RESTART 6 | 10 | #define SIGP_RESTART 6 |
10 | #define SIGP_STOP_AND_STORE_STATUS 9 | 11 | #define SIGP_STOP_AND_STORE_STATUS 9 |
@@ -12,6 +13,7 @@ | |||
12 | #define SIGP_SET_PREFIX 13 | 13 | #define SIGP_SET_PREFIX 13 |
13 | #define SIGP_STORE_STATUS_AT_ADDRESS 14 | 14 | #define SIGP_STORE_STATUS_AT_ADDRESS 14 |
14 | #define SIGP_SET_ARCHITECTURE 18 | 15 | #define SIGP_SET_ARCHITECTURE 18 |
16 | #define SIGP_COND_EMERGENCY_SIGNAL 19 | ||
15 | #define SIGP_SENSE_RUNNING 21 | 17 | #define SIGP_SENSE_RUNNING 21 |
16 | 18 | ||
17 | /* SIGP condition codes */ | 19 | /* SIGP condition codes */ |
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 5ff29be7d87a..8216c0e0b2e2 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
@@ -121,7 +121,7 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu) | |||
121 | * - gpr 4 contains the index on the bus (optionally) | 121 | * - gpr 4 contains the index on the bus (optionally) |
122 | */ | 122 | */ |
123 | ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS, | 123 | ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS, |
124 | vcpu->run->s.regs.gprs[2], | 124 | vcpu->run->s.regs.gprs[2] & 0xffffffff, |
125 | 8, &vcpu->run->s.regs.gprs[3], | 125 | 8, &vcpu->run->s.regs.gprs[3], |
126 | vcpu->run->s.regs.gprs[4]); | 126 | vcpu->run->s.regs.gprs[4]); |
127 | 127 | ||
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index c3700585b4bb..87c2b3a3bd3e 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * handling interprocessor communication | 2 | * handling interprocessor communication |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2008, 2009 | 4 | * Copyright IBM Corp. 2008, 2013 |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License (version 2 only) | 7 | * it under the terms of the GNU General Public License (version 2 only) |
@@ -89,6 +89,37 @@ unlock: | |||
89 | return rc; | 89 | return rc; |
90 | } | 90 | } |
91 | 91 | ||
92 | static int __sigp_conditional_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr, | ||
93 | u16 asn, u64 *reg) | ||
94 | { | ||
95 | struct kvm_vcpu *dst_vcpu = NULL; | ||
96 | const u64 psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT; | ||
97 | u16 p_asn, s_asn; | ||
98 | psw_t *psw; | ||
99 | u32 flags; | ||
100 | |||
101 | if (cpu_addr < KVM_MAX_VCPUS) | ||
102 | dst_vcpu = kvm_get_vcpu(vcpu->kvm, cpu_addr); | ||
103 | if (!dst_vcpu) | ||
104 | return SIGP_CC_NOT_OPERATIONAL; | ||
105 | flags = atomic_read(&dst_vcpu->arch.sie_block->cpuflags); | ||
106 | psw = &dst_vcpu->arch.sie_block->gpsw; | ||
107 | p_asn = dst_vcpu->arch.sie_block->gcr[4] & 0xffff; /* Primary ASN */ | ||
108 | s_asn = dst_vcpu->arch.sie_block->gcr[3] & 0xffff; /* Secondary ASN */ | ||
109 | |||
110 | /* Deliver the emergency signal? */ | ||
111 | if (!(flags & CPUSTAT_STOPPED) | ||
112 | || (psw->mask & psw_int_mask) != psw_int_mask | ||
113 | || ((flags & CPUSTAT_WAIT) && psw->addr != 0) | ||
114 | || (!(flags & CPUSTAT_WAIT) && (asn == p_asn || asn == s_asn))) { | ||
115 | return __sigp_emergency(vcpu, cpu_addr); | ||
116 | } else { | ||
117 | *reg &= 0xffffffff00000000UL; | ||
118 | *reg |= SIGP_STATUS_INCORRECT_STATE; | ||
119 | return SIGP_CC_STATUS_STORED; | ||
120 | } | ||
121 | } | ||
122 | |||
92 | static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) | 123 | static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) |
93 | { | 124 | { |
94 | struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; | 125 | struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; |
@@ -332,7 +363,8 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, | |||
332 | return rc; | 363 | return rc; |
333 | } | 364 | } |
334 | 365 | ||
335 | static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr) | 366 | /* Test whether the destination CPU is available and not busy */ |
367 | static int sigp_check_callable(struct kvm_vcpu *vcpu, u16 cpu_addr) | ||
336 | { | 368 | { |
337 | struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; | 369 | struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; |
338 | struct kvm_s390_local_interrupt *li; | 370 | struct kvm_s390_local_interrupt *li; |
@@ -351,9 +383,6 @@ static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr) | |||
351 | spin_lock_bh(&li->lock); | 383 | spin_lock_bh(&li->lock); |
352 | if (li->action_bits & ACTION_STOP_ON_STOP) | 384 | if (li->action_bits & ACTION_STOP_ON_STOP) |
353 | rc = SIGP_CC_BUSY; | 385 | rc = SIGP_CC_BUSY; |
354 | else | ||
355 | VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace", | ||
356 | cpu_addr); | ||
357 | spin_unlock_bh(&li->lock); | 386 | spin_unlock_bh(&li->lock); |
358 | out: | 387 | out: |
359 | spin_unlock(&fi->lock); | 388 | spin_unlock(&fi->lock); |
@@ -417,17 +446,31 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | |||
417 | rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, | 446 | rc = __sigp_set_prefix(vcpu, cpu_addr, parameter, |
418 | &vcpu->run->s.regs.gprs[r1]); | 447 | &vcpu->run->s.regs.gprs[r1]); |
419 | break; | 448 | break; |
449 | case SIGP_COND_EMERGENCY_SIGNAL: | ||
450 | rc = __sigp_conditional_emergency(vcpu, cpu_addr, parameter, | ||
451 | &vcpu->run->s.regs.gprs[r1]); | ||
452 | break; | ||
420 | case SIGP_SENSE_RUNNING: | 453 | case SIGP_SENSE_RUNNING: |
421 | vcpu->stat.instruction_sigp_sense_running++; | 454 | vcpu->stat.instruction_sigp_sense_running++; |
422 | rc = __sigp_sense_running(vcpu, cpu_addr, | 455 | rc = __sigp_sense_running(vcpu, cpu_addr, |
423 | &vcpu->run->s.regs.gprs[r1]); | 456 | &vcpu->run->s.regs.gprs[r1]); |
424 | break; | 457 | break; |
458 | case SIGP_START: | ||
459 | rc = sigp_check_callable(vcpu, cpu_addr); | ||
460 | if (rc == SIGP_CC_ORDER_CODE_ACCEPTED) | ||
461 | rc = -EOPNOTSUPP; /* Handle START in user space */ | ||
462 | break; | ||
425 | case SIGP_RESTART: | 463 | case SIGP_RESTART: |
426 | vcpu->stat.instruction_sigp_restart++; | 464 | vcpu->stat.instruction_sigp_restart++; |
427 | rc = __sigp_restart(vcpu, cpu_addr); | 465 | rc = sigp_check_callable(vcpu, cpu_addr); |
428 | if (rc == SIGP_CC_BUSY) | 466 | if (rc == SIGP_CC_ORDER_CODE_ACCEPTED) { |
429 | break; | 467 | VCPU_EVENT(vcpu, 4, |
430 | /* user space must know about restart */ | 468 | "sigp restart %x to handle userspace", |
469 | cpu_addr); | ||
470 | /* user space must know about restart */ | ||
471 | rc = -EOPNOTSUPP; | ||
472 | } | ||
473 | break; | ||
431 | default: | 474 | default: |
432 | return -EOPNOTSUPP; | 475 | return -EOPNOTSUPP; |
433 | } | 476 | } |
@@ -435,7 +478,6 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | |||
435 | if (rc < 0) | 478 | if (rc < 0) |
436 | return rc; | 479 | return rc; |
437 | 480 | ||
438 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | 481 | kvm_s390_set_psw_cc(vcpu, rc); |
439 | vcpu->arch.sie_block->gpsw.mask |= (rc & 3ul) << 44; | ||
440 | return 0; | 482 | return 0; |
441 | } | 483 | } |