diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2014-01-23 05:38:13 -0500 |
|---|---|---|
| committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-01-23 05:38:13 -0500 |
| commit | c760f5e29d92adf5184589f1e616a4be146fb57c (patch) | |
| tree | eae46255f2a1633fc29df5430989f3cfbb799b40 | |
| parent | 0dc3fd0249a295863900984e02dd4bb89204205b (diff) | |
| parent | 19e4735bd7f02bd38db43a8521377b35f236b3b6 (diff) | |
Merge tag 'kvm-s390-20140117' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into kvm-queue
This deals with 2 guest features that need enablement in the kvm host:
- transactional execution
- lpp sampling support
In addition there is also a fix to the virtio-ccw guest driver. This will
enable future features
| -rw-r--r-- | arch/s390/include/asm/kvm_host.h | 15 | ||||
| -rw-r--r-- | arch/s390/kvm/intercept.c | 11 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 17 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.h | 6 | ||||
| -rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 11 |
5 files changed, 51 insertions, 9 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index d5bc3750616e..eef3dd3fd9a9 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
| @@ -106,9 +106,22 @@ struct kvm_s390_sie_block { | |||
| 106 | __u64 gbea; /* 0x0180 */ | 106 | __u64 gbea; /* 0x0180 */ |
| 107 | __u8 reserved188[24]; /* 0x0188 */ | 107 | __u8 reserved188[24]; /* 0x0188 */ |
| 108 | __u32 fac; /* 0x01a0 */ | 108 | __u32 fac; /* 0x01a0 */ |
| 109 | __u8 reserved1a4[92]; /* 0x01a4 */ | 109 | __u8 reserved1a4[68]; /* 0x01a4 */ |
| 110 | __u64 itdba; /* 0x01e8 */ | ||
| 111 | __u8 reserved1f0[16]; /* 0x01f0 */ | ||
| 110 | } __attribute__((packed)); | 112 | } __attribute__((packed)); |
| 111 | 113 | ||
| 114 | struct kvm_s390_itdb { | ||
| 115 | __u8 data[256]; | ||
| 116 | } __packed; | ||
| 117 | |||
| 118 | struct sie_page { | ||
| 119 | struct kvm_s390_sie_block sie_block; | ||
| 120 | __u8 reserved200[1024]; /* 0x0200 */ | ||
| 121 | struct kvm_s390_itdb itdb; /* 0x0600 */ | ||
| 122 | __u8 reserved700[2304]; /* 0x0700 */ | ||
| 123 | } __packed; | ||
| 124 | |||
| 112 | struct kvm_vcpu_stat { | 125 | struct kvm_vcpu_stat { |
| 113 | u32 exit_userspace; | 126 | u32 exit_userspace; |
| 114 | u32 exit_null; | 127 | u32 exit_null; |
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 5ddbbde6f65c..eeb1ac7d8fa4 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c | |||
| @@ -112,6 +112,17 @@ static int handle_instruction(struct kvm_vcpu *vcpu) | |||
| 112 | static int handle_prog(struct kvm_vcpu *vcpu) | 112 | static int handle_prog(struct kvm_vcpu *vcpu) |
| 113 | { | 113 | { |
| 114 | vcpu->stat.exit_program_interruption++; | 114 | vcpu->stat.exit_program_interruption++; |
| 115 | |||
| 116 | /* Restore ITDB to Program-Interruption TDB in guest memory */ | ||
| 117 | if (IS_TE_ENABLED(vcpu) && | ||
| 118 | !(current->thread.per_flags & PER_FLAG_NO_TE) && | ||
| 119 | IS_ITDB_VALID(vcpu)) { | ||
| 120 | copy_to_guest(vcpu, TDB_ADDR, vcpu->arch.sie_block->itdba, | ||
| 121 | sizeof(struct kvm_s390_itdb)); | ||
| 122 | memset((void *) vcpu->arch.sie_block->itdba, 0, | ||
| 123 | sizeof(struct kvm_s390_itdb)); | ||
| 124 | } | ||
| 125 | |||
| 115 | trace_kvm_s390_intercept_prog(vcpu, vcpu->arch.sie_block->iprcc); | 126 | trace_kvm_s390_intercept_prog(vcpu, vcpu->arch.sie_block->iprcc); |
| 116 | return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc); | 127 | return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc); |
| 117 | } | 128 | } |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 7635c00a1479..e0676f390d57 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
| @@ -395,6 +395,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
| 395 | CPUSTAT_STOPPED | | 395 | CPUSTAT_STOPPED | |
| 396 | CPUSTAT_GED); | 396 | CPUSTAT_GED); |
| 397 | vcpu->arch.sie_block->ecb = 6; | 397 | vcpu->arch.sie_block->ecb = 6; |
| 398 | if (test_vfacility(50) && test_vfacility(73)) | ||
| 399 | vcpu->arch.sie_block->ecb |= 0x10; | ||
| 400 | |||
| 398 | vcpu->arch.sie_block->ecb2 = 8; | 401 | vcpu->arch.sie_block->ecb2 = 8; |
| 399 | vcpu->arch.sie_block->eca = 0xC1002001U; | 402 | vcpu->arch.sie_block->eca = 0xC1002001U; |
| 400 | vcpu->arch.sie_block->fac = (int) (long) vfacilities; | 403 | vcpu->arch.sie_block->fac = (int) (long) vfacilities; |
| @@ -411,6 +414,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, | |||
| 411 | unsigned int id) | 414 | unsigned int id) |
| 412 | { | 415 | { |
| 413 | struct kvm_vcpu *vcpu; | 416 | struct kvm_vcpu *vcpu; |
| 417 | struct sie_page *sie_page; | ||
| 414 | int rc = -EINVAL; | 418 | int rc = -EINVAL; |
| 415 | 419 | ||
| 416 | if (id >= KVM_MAX_VCPUS) | 420 | if (id >= KVM_MAX_VCPUS) |
| @@ -422,12 +426,13 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, | |||
| 422 | if (!vcpu) | 426 | if (!vcpu) |
| 423 | goto out; | 427 | goto out; |
| 424 | 428 | ||
| 425 | vcpu->arch.sie_block = (struct kvm_s390_sie_block *) | 429 | sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL); |
| 426 | get_zeroed_page(GFP_KERNEL); | 430 | if (!sie_page) |
| 427 | |||
| 428 | if (!vcpu->arch.sie_block) | ||
| 429 | goto out_free_cpu; | 431 | goto out_free_cpu; |
| 430 | 432 | ||
| 433 | vcpu->arch.sie_block = &sie_page->sie_block; | ||
| 434 | vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb; | ||
| 435 | |||
| 431 | vcpu->arch.sie_block->icpua = id; | 436 | vcpu->arch.sie_block->icpua = id; |
| 432 | if (!kvm_is_ucontrol(kvm)) { | 437 | if (!kvm_is_ucontrol(kvm)) { |
| 433 | if (!kvm->arch.sca) { | 438 | if (!kvm->arch.sca) { |
| @@ -1182,8 +1187,8 @@ static int __init kvm_s390_init(void) | |||
| 1182 | return -ENOMEM; | 1187 | return -ENOMEM; |
| 1183 | } | 1188 | } |
| 1184 | memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16); | 1189 | memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16); |
| 1185 | vfacilities[0] &= 0xff82fff3f47c0000UL; | 1190 | vfacilities[0] &= 0xff82fff3f4fc2000UL; |
| 1186 | vfacilities[1] &= 0x001c000000000000UL; | 1191 | vfacilities[1] &= 0x005c000000000000UL; |
| 1187 | return 0; | 1192 | return 0; |
| 1188 | } | 1193 | } |
| 1189 | 1194 | ||
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 095cf51b16ec..f9559b0bd620 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
| @@ -26,6 +26,12 @@ extern unsigned long *vfacilities; | |||
| 26 | 26 | ||
| 27 | int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); | 27 | int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); |
| 28 | 28 | ||
| 29 | /* Transactional Memory Execution related macros */ | ||
| 30 | #define IS_TE_ENABLED(vcpu) ((vcpu->arch.sie_block->ecb & 0x10)) | ||
| 31 | #define TDB_ADDR 0x1800UL | ||
| 32 | #define TDB_FORMAT1 1 | ||
| 33 | #define IS_ITDB_VALID(vcpu) ((*(char *)vcpu->arch.sie_block->itdba == TDB_FORMAT1)) | ||
| 34 | |||
| 29 | #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ | 35 | #define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ |
| 30 | do { \ | 36 | do { \ |
| 31 | debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \ | 37 | debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \ |
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index d6297176ab85..0fc584832001 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
| @@ -642,8 +642,15 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, | |||
| 642 | (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) { | 642 | (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) { |
| 643 | /* OK */ | 643 | /* OK */ |
| 644 | } | 644 | } |
| 645 | if (irb_is_error(irb)) | 645 | if (irb_is_error(irb)) { |
| 646 | vcdev->err = -EIO; /* XXX - use real error */ | 646 | /* Command reject? */ |
| 647 | if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) && | ||
| 648 | (irb->ecw[0] & SNS0_CMD_REJECT)) | ||
| 649 | vcdev->err = -EOPNOTSUPP; | ||
| 650 | else | ||
| 651 | /* Map everything else to -EIO. */ | ||
| 652 | vcdev->err = -EIO; | ||
| 653 | } | ||
| 647 | if (vcdev->curr_io & activity) { | 654 | if (vcdev->curr_io & activity) { |
| 648 | switch (activity) { | 655 | switch (activity) { |
| 649 | case VIRTIO_CCW_DOING_READ_FEAT: | 656 | case VIRTIO_CCW_DOING_READ_FEAT: |
