diff options
Diffstat (limited to 'arch/s390/kvm/kvm-s390.c')
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index e0676f390d57..10b5db3c9bc4 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -68,6 +68,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
68 | { "instruction_storage_key", VCPU_STAT(instruction_storage_key) }, | 68 | { "instruction_storage_key", VCPU_STAT(instruction_storage_key) }, |
69 | { "instruction_stsch", VCPU_STAT(instruction_stsch) }, | 69 | { "instruction_stsch", VCPU_STAT(instruction_stsch) }, |
70 | { "instruction_chsc", VCPU_STAT(instruction_chsc) }, | 70 | { "instruction_chsc", VCPU_STAT(instruction_chsc) }, |
71 | { "instruction_essa", VCPU_STAT(instruction_essa) }, | ||
71 | { "instruction_stsi", VCPU_STAT(instruction_stsi) }, | 72 | { "instruction_stsi", VCPU_STAT(instruction_stsi) }, |
72 | { "instruction_stfl", VCPU_STAT(instruction_stfl) }, | 73 | { "instruction_stfl", VCPU_STAT(instruction_stfl) }, |
73 | { "instruction_tprot", VCPU_STAT(instruction_tprot) }, | 74 | { "instruction_tprot", VCPU_STAT(instruction_tprot) }, |
@@ -283,7 +284,11 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) | |||
283 | if (kvm_is_ucontrol(vcpu->kvm)) | 284 | if (kvm_is_ucontrol(vcpu->kvm)) |
284 | gmap_free(vcpu->arch.gmap); | 285 | gmap_free(vcpu->arch.gmap); |
285 | 286 | ||
287 | if (vcpu->arch.sie_block->cbrlo) | ||
288 | __free_page(__pfn_to_page( | ||
289 | vcpu->arch.sie_block->cbrlo >> PAGE_SHIFT)); | ||
286 | free_page((unsigned long)(vcpu->arch.sie_block)); | 290 | free_page((unsigned long)(vcpu->arch.sie_block)); |
291 | |||
287 | kvm_vcpu_uninit(vcpu); | 292 | kvm_vcpu_uninit(vcpu); |
288 | kmem_cache_free(kvm_vcpu_cache, vcpu); | 293 | kmem_cache_free(kvm_vcpu_cache, vcpu); |
289 | } | 294 | } |
@@ -390,6 +395,8 @@ int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) | |||
390 | 395 | ||
391 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | 396 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) |
392 | { | 397 | { |
398 | struct page *cbrl; | ||
399 | |||
393 | atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | | 400 | atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | |
394 | CPUSTAT_SM | | 401 | CPUSTAT_SM | |
395 | CPUSTAT_STOPPED | | 402 | CPUSTAT_STOPPED | |
@@ -401,6 +408,14 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
401 | vcpu->arch.sie_block->ecb2 = 8; | 408 | vcpu->arch.sie_block->ecb2 = 8; |
402 | vcpu->arch.sie_block->eca = 0xC1002001U; | 409 | vcpu->arch.sie_block->eca = 0xC1002001U; |
403 | vcpu->arch.sie_block->fac = (int) (long) vfacilities; | 410 | vcpu->arch.sie_block->fac = (int) (long) vfacilities; |
411 | if (kvm_enabled_cmma()) { | ||
412 | cbrl = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
413 | if (cbrl) { | ||
414 | vcpu->arch.sie_block->ecb2 |= 0x80; | ||
415 | vcpu->arch.sie_block->ecb2 &= ~0x08; | ||
416 | vcpu->arch.sie_block->cbrlo = page_to_phys(cbrl); | ||
417 | } | ||
418 | } | ||
404 | hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); | 419 | hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
405 | tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, | 420 | tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, |
406 | (unsigned long) vcpu); | 421 | (unsigned long) vcpu); |
@@ -761,6 +776,16 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) | |||
761 | return rc; | 776 | return rc; |
762 | } | 777 | } |
763 | 778 | ||
779 | bool kvm_enabled_cmma(void) | ||
780 | { | ||
781 | if (!MACHINE_IS_LPAR) | ||
782 | return false; | ||
783 | /* only enable for z10 and later */ | ||
784 | if (!MACHINE_HAS_EDAT1) | ||
785 | return false; | ||
786 | return true; | ||
787 | } | ||
788 | |||
764 | static int __vcpu_run(struct kvm_vcpu *vcpu) | 789 | static int __vcpu_run(struct kvm_vcpu *vcpu) |
765 | { | 790 | { |
766 | int rc, exit_reason; | 791 | int rc, exit_reason; |