diff options
Diffstat (limited to 'arch/s390/kvm/kvm-s390.c')
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c18b21d6991c..90d9d1ba258b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <asm/lowcore.h> | 25 | #include <asm/lowcore.h> |
| 26 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
| 27 | #include <asm/nmi.h> | 27 | #include <asm/nmi.h> |
| 28 | #include <asm/system.h> | ||
| 28 | #include "kvm-s390.h" | 29 | #include "kvm-s390.h" |
| 29 | #include "gaccess.h" | 30 | #include "gaccess.h" |
| 30 | 31 | ||
| @@ -69,6 +70,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
| 69 | { NULL } | 70 | { NULL } |
| 70 | }; | 71 | }; |
| 71 | 72 | ||
| 73 | static unsigned long long *facilities; | ||
| 72 | 74 | ||
| 73 | /* Section: not file related */ | 75 | /* Section: not file related */ |
| 74 | void kvm_arch_hardware_enable(void *garbage) | 76 | void kvm_arch_hardware_enable(void *garbage) |
| @@ -288,6 +290,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
| 288 | vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin; | 290 | vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin; |
| 289 | vcpu->arch.sie_block->ecb = 2; | 291 | vcpu->arch.sie_block->ecb = 2; |
| 290 | vcpu->arch.sie_block->eca = 0xC1002001U; | 292 | vcpu->arch.sie_block->eca = 0xC1002001U; |
| 293 | vcpu->arch.sie_block->fac = (int) (long) facilities; | ||
| 291 | hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); | 294 | hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
| 292 | tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, | 295 | tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, |
| 293 | (unsigned long) vcpu); | 296 | (unsigned long) vcpu); |
| @@ -739,11 +742,29 @@ gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) | |||
| 739 | 742 | ||
| 740 | static int __init kvm_s390_init(void) | 743 | static int __init kvm_s390_init(void) |
| 741 | { | 744 | { |
| 742 | return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE); | 745 | int ret; |
| 746 | ret = kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE); | ||
| 747 | if (ret) | ||
| 748 | return ret; | ||
| 749 | |||
| 750 | /* | ||
| 751 | * guests can ask for up to 255+1 double words, we need a full page | ||
| 752 | * to hold the maximum amount of facilites. On the other hand, we | ||
| 753 | * only set facilities that are known to work in KVM. | ||
| 754 | */ | ||
| 755 | facilities = (unsigned long long *) get_zeroed_page(GFP_DMA); | ||
| 756 | if (!facilities) { | ||
| 757 | kvm_exit(); | ||
| 758 | return -ENOMEM; | ||
| 759 | } | ||
| 760 | stfle(facilities, 1); | ||
| 761 | facilities[0] &= 0xff00fff3f0700000ULL; | ||
| 762 | return 0; | ||
| 743 | } | 763 | } |
| 744 | 764 | ||
| 745 | static void __exit kvm_s390_exit(void) | 765 | static void __exit kvm_s390_exit(void) |
| 746 | { | 766 | { |
| 767 | free_page((unsigned long) facilities); | ||
| 747 | kvm_exit(); | 768 | kvm_exit(); |
| 748 | } | 769 | } |
| 749 | 770 | ||
