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 /arch/s390 | |
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
Diffstat (limited to 'arch/s390')
-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 |
4 files changed, 42 insertions, 7 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", \ |