diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 4 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 23 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 2 |
3 files changed, 26 insertions, 3 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index a27d0d5a6f86..1cd02f6073a0 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
@@ -99,7 +99,9 @@ struct kvm_s390_sie_block { | |||
99 | __u8 reservedd0[48]; /* 0x00d0 */ | 99 | __u8 reservedd0[48]; /* 0x00d0 */ |
100 | __u64 gcr[16]; /* 0x0100 */ | 100 | __u64 gcr[16]; /* 0x0100 */ |
101 | __u64 gbea; /* 0x0180 */ | 101 | __u64 gbea; /* 0x0180 */ |
102 | __u8 reserved188[120]; /* 0x0188 */ | 102 | __u8 reserved188[24]; /* 0x0188 */ |
103 | __u32 fac; /* 0x01a0 */ | ||
104 | __u8 reserved1a4[92]; /* 0x01a4 */ | ||
103 | } __attribute__((packed)); | 105 | } __attribute__((packed)); |
104 | 106 | ||
105 | struct kvm_vcpu_stat { | 107 | struct kvm_vcpu_stat { |
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 | ||
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 93ecd06e1a74..d426aac8095d 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -158,7 +158,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu) | |||
158 | 158 | ||
159 | vcpu->stat.instruction_stfl++; | 159 | vcpu->stat.instruction_stfl++; |
160 | /* only pass the facility bits, which we can handle */ | 160 | /* only pass the facility bits, which we can handle */ |
161 | facility_list &= 0xfe00fff3; | 161 | facility_list &= 0xff00fff3; |
162 | 162 | ||
163 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), | 163 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), |
164 | &facility_list, sizeof(facility_list)); | 164 | &facility_list, sizeof(facility_list)); |