diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-09-11 05:09:33 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-09-11 05:09:33 -0400 |
commit | 2c69c1a32140262d5d6104ab96df2e52c08c1e93 (patch) | |
tree | 6cf99e80917ea03591031c6801704a5668fc9310 | |
parent | 209cf19fcd927e6db9f2ef38e3ca6afdcc0d4d5a (diff) | |
parent | bfac1f59a1afb13a3cf225bffd04be99a49c51a6 (diff) |
Merge tag 'kvm-s390-next-20140910' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into kvm-next
KVM: s390: Fixes and features for next (3.18)
1. Crypto/CPACF support: To enable the MSA4 instructions we have to
provide a common control structure for each SIE control block
2. Two cleanups found by a static code checker: one redundant assignment
and one useless if
3. Fix the page handling of the diag10 ballooning interface. If the
guest freed the pages at absolute 0 some checks and frees were
incorrect
4. Limit guests to 16TB
5. Add __must_check to interrupt injection code
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 14 | ||||
-rw-r--r-- | arch/s390/kvm/diag.c | 26 | ||||
-rw-r--r-- | arch/s390/kvm/gaccess.c | 3 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 14 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 35 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 2 |
6 files changed, 74 insertions, 20 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index a76a124dff48..1a6f6fd8bd34 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
@@ -157,7 +157,9 @@ struct kvm_s390_sie_block { | |||
157 | __u8 armid; /* 0x00e3 */ | 157 | __u8 armid; /* 0x00e3 */ |
158 | __u8 reservede4[4]; /* 0x00e4 */ | 158 | __u8 reservede4[4]; /* 0x00e4 */ |
159 | __u64 tecmc; /* 0x00e8 */ | 159 | __u64 tecmc; /* 0x00e8 */ |
160 | __u8 reservedf0[16]; /* 0x00f0 */ | 160 | __u8 reservedf0[12]; /* 0x00f0 */ |
161 | #define CRYCB_FORMAT1 0x00000001 | ||
162 | __u32 crycbd; /* 0x00fc */ | ||
161 | __u64 gcr[16]; /* 0x0100 */ | 163 | __u64 gcr[16]; /* 0x0100 */ |
162 | __u64 gbea; /* 0x0180 */ | 164 | __u64 gbea; /* 0x0180 */ |
163 | __u8 reserved188[24]; /* 0x0188 */ | 165 | __u8 reserved188[24]; /* 0x0188 */ |
@@ -410,6 +412,15 @@ struct s390_io_adapter { | |||
410 | #define MAX_S390_IO_ADAPTERS ((MAX_ISC + 1) * 8) | 412 | #define MAX_S390_IO_ADAPTERS ((MAX_ISC + 1) * 8) |
411 | #define MAX_S390_ADAPTER_MAPS 256 | 413 | #define MAX_S390_ADAPTER_MAPS 256 |
412 | 414 | ||
415 | struct kvm_s390_crypto { | ||
416 | struct kvm_s390_crypto_cb *crycb; | ||
417 | __u32 crycbd; | ||
418 | }; | ||
419 | |||
420 | struct kvm_s390_crypto_cb { | ||
421 | __u8 reserved00[128]; /* 0x0000 */ | ||
422 | }; | ||
423 | |||
413 | struct kvm_arch{ | 424 | struct kvm_arch{ |
414 | struct sca_block *sca; | 425 | struct sca_block *sca; |
415 | debug_info_t *dbf; | 426 | debug_info_t *dbf; |
@@ -423,6 +434,7 @@ struct kvm_arch{ | |||
423 | struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS]; | 434 | struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS]; |
424 | wait_queue_head_t ipte_wq; | 435 | wait_queue_head_t ipte_wq; |
425 | spinlock_t start_stop_lock; | 436 | spinlock_t start_stop_lock; |
437 | struct kvm_s390_crypto crypto; | ||
426 | }; | 438 | }; |
427 | 439 | ||
428 | #define KVM_HVA_ERR_BAD (-1UL) | 440 | #define KVM_HVA_ERR_BAD (-1UL) |
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index b374b6cb7785..9254afff250c 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
@@ -28,22 +28,32 @@ static int diag_release_pages(struct kvm_vcpu *vcpu) | |||
28 | start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; | 28 | start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; |
29 | end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096; | 29 | end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096; |
30 | 30 | ||
31 | if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end | 31 | if (start & ~PAGE_MASK || end & ~PAGE_MASK || start >= end |
32 | || start < 2 * PAGE_SIZE) | 32 | || start < 2 * PAGE_SIZE) |
33 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 33 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
34 | 34 | ||
35 | VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end); | 35 | VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end); |
36 | vcpu->stat.diagnose_10++; | 36 | vcpu->stat.diagnose_10++; |
37 | 37 | ||
38 | /* we checked for start > end above */ | 38 | /* |
39 | if (end < prefix || start >= prefix + 2 * PAGE_SIZE) { | 39 | * We checked for start >= end above, so lets check for the |
40 | * fast path (no prefix swap page involved) | ||
41 | */ | ||
42 | if (end <= prefix || start >= prefix + 2 * PAGE_SIZE) { | ||
40 | gmap_discard(vcpu->arch.gmap, start, end); | 43 | gmap_discard(vcpu->arch.gmap, start, end); |
41 | } else { | 44 | } else { |
42 | if (start < prefix) | 45 | /* |
43 | gmap_discard(vcpu->arch.gmap, start, prefix); | 46 | * This is slow path. gmap_discard will check for start |
44 | if (end >= prefix) | 47 | * so lets split this into before prefix, prefix, after |
45 | gmap_discard(vcpu->arch.gmap, | 48 | * prefix and let gmap_discard make some of these calls |
46 | prefix + 2 * PAGE_SIZE, end); | 49 | * NOPs. |
50 | */ | ||
51 | gmap_discard(vcpu->arch.gmap, start, prefix); | ||
52 | if (start <= prefix) | ||
53 | gmap_discard(vcpu->arch.gmap, 0, 4096); | ||
54 | if (end > prefix + 4096) | ||
55 | gmap_discard(vcpu->arch.gmap, 4096, 8192); | ||
56 | gmap_discard(vcpu->arch.gmap, prefix + 2 * PAGE_SIZE, end); | ||
47 | } | 57 | } |
48 | return 0; | 58 | return 0; |
49 | } | 59 | } |
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index 4653ac6e182b..0f961a1c64b3 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c | |||
@@ -254,8 +254,7 @@ static void ipte_unlock_simple(struct kvm_vcpu *vcpu) | |||
254 | new = old = ACCESS_ONCE(*ic); | 254 | new = old = ACCESS_ONCE(*ic); |
255 | new.k = 0; | 255 | new.k = 0; |
256 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); | 256 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); |
257 | if (!ipte_lock_count) | 257 | wake_up(&vcpu->kvm->arch.ipte_wq); |
258 | wake_up(&vcpu->kvm->arch.ipte_wq); | ||
259 | out: | 258 | out: |
260 | mutex_unlock(&ipte_mutex); | 259 | mutex_unlock(&ipte_mutex); |
261 | } | 260 | } |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 60a5cf40d49a..4cad00adef93 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #define IOINT_AI_MASK 0x04000000 | 28 | #define IOINT_AI_MASK 0x04000000 |
29 | #define PFAULT_INIT 0x0600 | 29 | #define PFAULT_INIT 0x0600 |
30 | 30 | ||
31 | static int deliver_ckc_interrupt(struct kvm_vcpu *vcpu); | 31 | static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu); |
32 | 32 | ||
33 | static int is_ioint(u64 type) | 33 | static int is_ioint(u64 type) |
34 | { | 34 | { |
@@ -77,7 +77,7 @@ static u64 int_word_to_isc_bits(u32 int_word) | |||
77 | return (0x80 >> isc) << 24; | 77 | return (0x80 >> isc) << 24; |
78 | } | 78 | } |
79 | 79 | ||
80 | static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, | 80 | static int __must_check __interrupt_is_deliverable(struct kvm_vcpu *vcpu, |
81 | struct kvm_s390_interrupt_info *inti) | 81 | struct kvm_s390_interrupt_info *inti) |
82 | { | 82 | { |
83 | switch (inti->type) { | 83 | switch (inti->type) { |
@@ -86,6 +86,7 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, | |||
86 | return 0; | 86 | return 0; |
87 | if (vcpu->arch.sie_block->gcr[0] & 0x2000ul) | 87 | if (vcpu->arch.sie_block->gcr[0] & 0x2000ul) |
88 | return 1; | 88 | return 1; |
89 | return 0; | ||
89 | case KVM_S390_INT_EMERGENCY: | 90 | case KVM_S390_INT_EMERGENCY: |
90 | if (psw_extint_disabled(vcpu)) | 91 | if (psw_extint_disabled(vcpu)) |
91 | return 0; | 92 | return 0; |
@@ -225,7 +226,7 @@ static u16 get_ilc(struct kvm_vcpu *vcpu) | |||
225 | } | 226 | } |
226 | } | 227 | } |
227 | 228 | ||
228 | static int __deliver_prog_irq(struct kvm_vcpu *vcpu, | 229 | static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, |
229 | struct kvm_s390_pgm_info *pgm_info) | 230 | struct kvm_s390_pgm_info *pgm_info) |
230 | { | 231 | { |
231 | int rc = 0; | 232 | int rc = 0; |
@@ -307,7 +308,7 @@ static int __deliver_prog_irq(struct kvm_vcpu *vcpu, | |||
307 | return rc; | 308 | return rc; |
308 | } | 309 | } |
309 | 310 | ||
310 | static int __do_deliver_interrupt(struct kvm_vcpu *vcpu, | 311 | static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, |
311 | struct kvm_s390_interrupt_info *inti) | 312 | struct kvm_s390_interrupt_info *inti) |
312 | { | 313 | { |
313 | const unsigned short table[] = { 2, 4, 4, 6 }; | 314 | const unsigned short table[] = { 2, 4, 4, 6 }; |
@@ -508,7 +509,7 @@ static int __do_deliver_interrupt(struct kvm_vcpu *vcpu, | |||
508 | return rc; | 509 | return rc; |
509 | } | 510 | } |
510 | 511 | ||
511 | static int deliver_ckc_interrupt(struct kvm_vcpu *vcpu) | 512 | static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu) |
512 | { | 513 | { |
513 | int rc; | 514 | int rc; |
514 | 515 | ||
@@ -657,7 +658,7 @@ void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu) | |||
657 | &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl); | 658 | &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl); |
658 | } | 659 | } |
659 | 660 | ||
660 | int kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) | 661 | int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) |
661 | { | 662 | { |
662 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 663 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
663 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; | 664 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; |
@@ -1351,7 +1352,6 @@ static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | |||
1351 | r = enqueue_floating_irq(dev, attr); | 1352 | r = enqueue_floating_irq(dev, attr); |
1352 | break; | 1353 | break; |
1353 | case KVM_DEV_FLIC_CLEAR_IRQS: | 1354 | case KVM_DEV_FLIC_CLEAR_IRQS: |
1354 | r = 0; | ||
1355 | kvm_s390_clear_float_irqs(dev->kvm); | 1355 | kvm_s390_clear_float_irqs(dev->kvm); |
1356 | break; | 1356 | break; |
1357 | case KVM_DEV_FLIC_APF_ENABLE: | 1357 | case KVM_DEV_FLIC_APF_ENABLE: |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 628e992eeded..b95d4a481b0c 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -392,6 +392,22 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
392 | return r; | 392 | return r; |
393 | } | 393 | } |
394 | 394 | ||
395 | static int kvm_s390_crypto_init(struct kvm *kvm) | ||
396 | { | ||
397 | if (!test_vfacility(76)) | ||
398 | return 0; | ||
399 | |||
400 | kvm->arch.crypto.crycb = kzalloc(sizeof(*kvm->arch.crypto.crycb), | ||
401 | GFP_KERNEL | GFP_DMA); | ||
402 | if (!kvm->arch.crypto.crycb) | ||
403 | return -ENOMEM; | ||
404 | |||
405 | kvm->arch.crypto.crycbd = (__u32) (unsigned long) kvm->arch.crypto.crycb | | ||
406 | CRYCB_FORMAT1; | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
395 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | 411 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) |
396 | { | 412 | { |
397 | int rc; | 413 | int rc; |
@@ -429,6 +445,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
429 | if (!kvm->arch.dbf) | 445 | if (!kvm->arch.dbf) |
430 | goto out_nodbf; | 446 | goto out_nodbf; |
431 | 447 | ||
448 | if (kvm_s390_crypto_init(kvm) < 0) | ||
449 | goto out_crypto; | ||
450 | |||
432 | spin_lock_init(&kvm->arch.float_int.lock); | 451 | spin_lock_init(&kvm->arch.float_int.lock); |
433 | INIT_LIST_HEAD(&kvm->arch.float_int.list); | 452 | INIT_LIST_HEAD(&kvm->arch.float_int.list); |
434 | init_waitqueue_head(&kvm->arch.ipte_wq); | 453 | init_waitqueue_head(&kvm->arch.ipte_wq); |
@@ -439,7 +458,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
439 | if (type & KVM_VM_S390_UCONTROL) { | 458 | if (type & KVM_VM_S390_UCONTROL) { |
440 | kvm->arch.gmap = NULL; | 459 | kvm->arch.gmap = NULL; |
441 | } else { | 460 | } else { |
442 | kvm->arch.gmap = gmap_alloc(current->mm, -1UL); | 461 | kvm->arch.gmap = gmap_alloc(current->mm, (1UL << 44) - 1); |
443 | if (!kvm->arch.gmap) | 462 | if (!kvm->arch.gmap) |
444 | goto out_nogmap; | 463 | goto out_nogmap; |
445 | kvm->arch.gmap->private = kvm; | 464 | kvm->arch.gmap->private = kvm; |
@@ -453,6 +472,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
453 | 472 | ||
454 | return 0; | 473 | return 0; |
455 | out_nogmap: | 474 | out_nogmap: |
475 | kfree(kvm->arch.crypto.crycb); | ||
476 | out_crypto: | ||
456 | debug_unregister(kvm->arch.dbf); | 477 | debug_unregister(kvm->arch.dbf); |
457 | out_nodbf: | 478 | out_nodbf: |
458 | free_page((unsigned long)(kvm->arch.sca)); | 479 | free_page((unsigned long)(kvm->arch.sca)); |
@@ -507,6 +528,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm) | |||
507 | kvm_free_vcpus(kvm); | 528 | kvm_free_vcpus(kvm); |
508 | free_page((unsigned long)(kvm->arch.sca)); | 529 | free_page((unsigned long)(kvm->arch.sca)); |
509 | debug_unregister(kvm->arch.dbf); | 530 | debug_unregister(kvm->arch.dbf); |
531 | kfree(kvm->arch.crypto.crycb); | ||
510 | if (!kvm_is_ucontrol(kvm)) | 532 | if (!kvm_is_ucontrol(kvm)) |
511 | gmap_free(kvm->arch.gmap); | 533 | gmap_free(kvm->arch.gmap); |
512 | kvm_s390_destroy_adapters(kvm); | 534 | kvm_s390_destroy_adapters(kvm); |
@@ -588,6 +610,14 @@ int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) | |||
588 | return 0; | 610 | return 0; |
589 | } | 611 | } |
590 | 612 | ||
613 | static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu) | ||
614 | { | ||
615 | if (!test_vfacility(76)) | ||
616 | return; | ||
617 | |||
618 | vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd; | ||
619 | } | ||
620 | |||
591 | void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu) | 621 | void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu) |
592 | { | 622 | { |
593 | free_page(vcpu->arch.sie_block->cbrlo); | 623 | free_page(vcpu->arch.sie_block->cbrlo); |
@@ -634,6 +664,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
634 | vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup; | 664 | vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup; |
635 | get_cpu_id(&vcpu->arch.cpu_id); | 665 | get_cpu_id(&vcpu->arch.cpu_id); |
636 | vcpu->arch.cpu_id.version = 0xff; | 666 | vcpu->arch.cpu_id.version = 0xff; |
667 | |||
668 | kvm_s390_vcpu_crypto_setup(vcpu); | ||
669 | |||
637 | return rc; | 670 | return rc; |
638 | } | 671 | } |
639 | 672 | ||
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 99abcb56e478..b1a77669137b 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -138,7 +138,7 @@ static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm) | |||
138 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); | 138 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); |
139 | void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu); | 139 | void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu); |
140 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); | 140 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); |
141 | int kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu); | 141 | int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu); |
142 | void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu); | 142 | void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu); |
143 | void kvm_s390_clear_float_irqs(struct kvm *kvm); | 143 | void kvm_s390_clear_float_irqs(struct kvm *kvm); |
144 | int __must_check kvm_s390_inject_vm(struct kvm *kvm, | 144 | int __must_check kvm_s390_inject_vm(struct kvm *kvm, |