aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-01-23 05:38:13 -0500
committerPaolo Bonzini <pbonzini@redhat.com>2014-01-23 05:38:13 -0500
commitc760f5e29d92adf5184589f1e616a4be146fb57c (patch)
treeeae46255f2a1633fc29df5430989f3cfbb799b40 /arch/s390
parent0dc3fd0249a295863900984e02dd4bb89204205b (diff)
parent19e4735bd7f02bd38db43a8521377b35f236b3b6 (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.h15
-rw-r--r--arch/s390/kvm/intercept.c11
-rw-r--r--arch/s390/kvm/kvm-s390.c17
-rw-r--r--arch/s390/kvm/kvm-s390.h6
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
114struct kvm_s390_itdb {
115 __u8 data[256];
116} __packed;
117
118struct 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
112struct kvm_vcpu_stat { 125struct 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)
112static int handle_prog(struct kvm_vcpu *vcpu) 112static 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
27int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); 27int 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...)\
30do { \ 36do { \
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", \