aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/kvm/kvm-s390.c23
-rw-r--r--arch/s390/kvm/kvm-s390.h3
-rw-r--r--arch/s390/kvm/priv.c11
3 files changed, 22 insertions, 15 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index a3d797b689a3..ac8e6670c551 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -28,6 +28,7 @@
28#include <asm/pgtable.h> 28#include <asm/pgtable.h>
29#include <asm/nmi.h> 29#include <asm/nmi.h>
30#include <asm/switch_to.h> 30#include <asm/switch_to.h>
31#include <asm/facility.h>
31#include <asm/sclp.h> 32#include <asm/sclp.h>
32#include "kvm-s390.h" 33#include "kvm-s390.h"
33#include "gaccess.h" 34#include "gaccess.h"
@@ -84,9 +85,15 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
84 { NULL } 85 { NULL }
85}; 86};
86 87
87static unsigned long long *facilities; 88unsigned long *vfacilities;
88static struct gmap_notifier gmap_notifier; 89static struct gmap_notifier gmap_notifier;
89 90
91/* test availability of vfacility */
92static inline int test_vfacility(unsigned long nr)
93{
94 return __test_facility(nr, (void *) vfacilities);
95}
96
90/* Section: not file related */ 97/* Section: not file related */
91int kvm_arch_hardware_enable(void *garbage) 98int kvm_arch_hardware_enable(void *garbage)
92{ 99{
@@ -387,7 +394,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
387 vcpu->arch.sie_block->ecb = 6; 394 vcpu->arch.sie_block->ecb = 6;
388 vcpu->arch.sie_block->ecb2 = 8; 395 vcpu->arch.sie_block->ecb2 = 8;
389 vcpu->arch.sie_block->eca = 0xC1002001U; 396 vcpu->arch.sie_block->eca = 0xC1002001U;
390 vcpu->arch.sie_block->fac = (int) (long) facilities; 397 vcpu->arch.sie_block->fac = (int) (long) vfacilities;
391 hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); 398 hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
392 tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet, 399 tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
393 (unsigned long) vcpu); 400 (unsigned long) vcpu);
@@ -1126,20 +1133,20 @@ static int __init kvm_s390_init(void)
1126 * to hold the maximum amount of facilities. On the other hand, we 1133 * to hold the maximum amount of facilities. On the other hand, we
1127 * only set facilities that are known to work in KVM. 1134 * only set facilities that are known to work in KVM.
1128 */ 1135 */
1129 facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA); 1136 vfacilities = (unsigned long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
1130 if (!facilities) { 1137 if (!vfacilities) {
1131 kvm_exit(); 1138 kvm_exit();
1132 return -ENOMEM; 1139 return -ENOMEM;
1133 } 1140 }
1134 memcpy(facilities, S390_lowcore.stfle_fac_list, 16); 1141 memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16);
1135 facilities[0] &= 0xff82fff3f47c0000ULL; 1142 vfacilities[0] &= 0xff82fff3f47c0000UL;
1136 facilities[1] &= 0x001c000000000000ULL; 1143 vfacilities[1] &= 0x001c000000000000UL;
1137 return 0; 1144 return 0;
1138} 1145}
1139 1146
1140static void __exit kvm_s390_exit(void) 1147static void __exit kvm_s390_exit(void)
1141{ 1148{
1142 free_page((unsigned long) facilities); 1149 free_page((unsigned long) vfacilities);
1143 kvm_exit(); 1150 kvm_exit();
1144} 1151}
1145 1152
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 028ca9fd2158..faa4df633474 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -24,6 +24,9 @@
24 24
25typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu); 25typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
26 26
27/* declare vfacilities extern */
28extern unsigned long *vfacilities;
29
27/* negativ values are error codes, positive values for internal conditions */ 30/* negativ values are error codes, positive values for internal conditions */
28#define SIE_INTERCEPT_RERUNVCPU (1<<0) 31#define SIE_INTERCEPT_RERUNVCPU (1<<0)
29#define SIE_INTERCEPT_UCONTROL (1<<1) 32#define SIE_INTERCEPT_UCONTROL (1<<1)
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 0da3e6eb6be6..a14c4b68aed7 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -227,7 +227,6 @@ static int handle_io_inst(struct kvm_vcpu *vcpu)
227 227
228static int handle_stfl(struct kvm_vcpu *vcpu) 228static int handle_stfl(struct kvm_vcpu *vcpu)
229{ 229{
230 unsigned int facility_list;
231 int rc; 230 int rc;
232 231
233 vcpu->stat.instruction_stfl++; 232 vcpu->stat.instruction_stfl++;
@@ -235,15 +234,13 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
235 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) 234 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
236 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); 235 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
237 236
238 /* only pass the facility bits, which we can handle */
239 facility_list = S390_lowcore.stfl_fac_list & 0xff82fff3;
240
241 rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), 237 rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
242 &facility_list, sizeof(facility_list)); 238 vfacilities, 4);
243 if (rc) 239 if (rc)
244 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 240 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
245 VCPU_EVENT(vcpu, 5, "store facility list value %x", facility_list); 241 VCPU_EVENT(vcpu, 5, "store facility list value %x",
246 trace_kvm_s390_handle_stfl(vcpu, facility_list); 242 *(unsigned int *) vfacilities);
243 trace_kvm_s390_handle_stfl(vcpu, *(unsigned int *) vfacilities);
247 return 0; 244 return 0;
248} 245}
249 246