aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/kvm.h5
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/include/asm/kvm_para.h5
-rw-r--r--arch/s390/include/asm/sclp.h1
-rw-r--r--arch/s390/kvm/diag.c29
-rw-r--r--arch/s390/kvm/intercept.c1
-rw-r--r--arch/s390/kvm/kvm-s390.c87
-rw-r--r--arch/s390/kvm/kvm-s390.h1
-rw-r--r--arch/s390/kvm/priv.c31
9 files changed, 158 insertions, 3 deletions
diff --git a/arch/s390/include/asm/kvm.h b/arch/s390/include/asm/kvm.h
index 96076676e224..bdcbe0f8dd7b 100644
--- a/arch/s390/include/asm/kvm.h
+++ b/arch/s390/include/asm/kvm.h
@@ -52,4 +52,9 @@ struct kvm_sync_regs {
52 __u32 acrs[16]; /* access registers */ 52 __u32 acrs[16]; /* access registers */
53 __u64 crs[16]; /* control registers */ 53 __u64 crs[16]; /* control registers */
54}; 54};
55
56#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
57#define KVM_REG_S390_EPOCHDIFF (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x2)
58#define KVM_REG_S390_CPU_TIMER (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x3)
59#define KVM_REG_S390_CLOCK_COMP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x4)
55#endif 60#endif
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 7343872890a2..dd17537b9a9d 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -148,6 +148,7 @@ struct kvm_vcpu_stat {
148 u32 instruction_sigp_restart; 148 u32 instruction_sigp_restart;
149 u32 diagnose_10; 149 u32 diagnose_10;
150 u32 diagnose_44; 150 u32 diagnose_44;
151 u32 diagnose_9c;
151}; 152};
152 153
153struct kvm_s390_io_info { 154struct kvm_s390_io_info {
diff --git a/arch/s390/include/asm/kvm_para.h b/arch/s390/include/asm/kvm_para.h
index 6964db226f83..a98832961035 100644
--- a/arch/s390/include/asm/kvm_para.h
+++ b/arch/s390/include/asm/kvm_para.h
@@ -149,6 +149,11 @@ static inline unsigned int kvm_arch_para_features(void)
149 return 0; 149 return 0;
150} 150}
151 151
152static inline bool kvm_check_and_clear_guest_paused(void)
153{
154 return false;
155}
156
152#endif 157#endif
153 158
154#endif /* __S390_KVM_PARA_H */ 159#endif /* __S390_KVM_PARA_H */
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index fed7bee650a0..bf238c55740b 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -48,6 +48,7 @@ int sclp_cpu_deconfigure(u8 cpu);
48void sclp_facilities_detect(void); 48void sclp_facilities_detect(void);
49unsigned long long sclp_get_rnmax(void); 49unsigned long long sclp_get_rnmax(void);
50unsigned long long sclp_get_rzm(void); 50unsigned long long sclp_get_rzm(void);
51u8 sclp_get_fac85(void);
51int sclp_sdias_blk_count(void); 52int sclp_sdias_blk_count(void);
52int sclp_sdias_copy(void *dest, int blk_num, int nr_blks); 53int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
53int sclp_chp_configure(struct chp_id chpid); 54int sclp_chp_configure(struct chp_id chpid);
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index a353f0ea45c2..b23d9ac77dfc 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -47,9 +47,30 @@ static int __diag_time_slice_end(struct kvm_vcpu *vcpu)
47{ 47{
48 VCPU_EVENT(vcpu, 5, "%s", "diag time slice end"); 48 VCPU_EVENT(vcpu, 5, "%s", "diag time slice end");
49 vcpu->stat.diagnose_44++; 49 vcpu->stat.diagnose_44++;
50 vcpu_put(vcpu); 50 kvm_vcpu_on_spin(vcpu);
51 yield(); 51 return 0;
52 vcpu_load(vcpu); 52}
53
54static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu)
55{
56 struct kvm *kvm = vcpu->kvm;
57 struct kvm_vcpu *tcpu;
58 int tid;
59 int i;
60
61 tid = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
62 vcpu->stat.diagnose_9c++;
63 VCPU_EVENT(vcpu, 5, "diag time slice end directed to %d", tid);
64
65 if (tid == vcpu->vcpu_id)
66 return 0;
67
68 kvm_for_each_vcpu(i, tcpu, kvm)
69 if (tcpu->vcpu_id == tid) {
70 kvm_vcpu_yield_to(tcpu);
71 break;
72 }
73
53 return 0; 74 return 0;
54} 75}
55 76
@@ -89,6 +110,8 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
89 return diag_release_pages(vcpu); 110 return diag_release_pages(vcpu);
90 case 0x44: 111 case 0x44:
91 return __diag_time_slice_end(vcpu); 112 return __diag_time_slice_end(vcpu);
113 case 0x9c:
114 return __diag_time_slice_end_directed(vcpu);
92 case 0x308: 115 case 0x308:
93 return __diag_ipl_functions(vcpu); 116 return __diag_ipl_functions(vcpu);
94 default: 117 default:
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 361456577c6f..979cbe55bf5e 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -101,6 +101,7 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
101} 101}
102 102
103static intercept_handler_t instruction_handlers[256] = { 103static intercept_handler_t instruction_handlers[256] = {
104 [0x01] = kvm_s390_handle_01,
104 [0x83] = kvm_s390_handle_diag, 105 [0x83] = kvm_s390_handle_diag,
105 [0xae] = kvm_s390_handle_sigp, 106 [0xae] = kvm_s390_handle_sigp,
106 [0xb2] = kvm_s390_handle_b2, 107 [0xb2] = kvm_s390_handle_b2,
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 217ce44395a4..664766d0c83c 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/sclp.h>
31#include "kvm-s390.h" 32#include "kvm-s390.h"
32#include "gaccess.h" 33#include "gaccess.h"
33 34
@@ -74,6 +75,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
74 { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) }, 75 { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
75 { "diagnose_10", VCPU_STAT(diagnose_10) }, 76 { "diagnose_10", VCPU_STAT(diagnose_10) },
76 { "diagnose_44", VCPU_STAT(diagnose_44) }, 77 { "diagnose_44", VCPU_STAT(diagnose_44) },
78 { "diagnose_9c", VCPU_STAT(diagnose_9c) },
77 { NULL } 79 { NULL }
78}; 80};
79 81
@@ -133,8 +135,16 @@ int kvm_dev_ioctl_check_extension(long ext)
133 case KVM_CAP_S390_UCONTROL: 135 case KVM_CAP_S390_UCONTROL:
134#endif 136#endif
135 case KVM_CAP_SYNC_REGS: 137 case KVM_CAP_SYNC_REGS:
138 case KVM_CAP_ONE_REG:
136 r = 1; 139 r = 1;
137 break; 140 break;
141 case KVM_CAP_NR_VCPUS:
142 case KVM_CAP_MAX_VCPUS:
143 r = KVM_MAX_VCPUS;
144 break;
145 case KVM_CAP_S390_COW:
146 r = sclp_get_fac85() & 0x2;
147 break;
138 default: 148 default:
139 r = 0; 149 r = 0;
140 } 150 }
@@ -423,6 +433,71 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
423 return 0; 433 return 0;
424} 434}
425 435
436int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
437{
438 /* kvm common code refers to this, but never calls it */
439 BUG();
440 return 0;
441}
442
443static int kvm_arch_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu,
444 struct kvm_one_reg *reg)
445{
446 int r = -EINVAL;
447
448 switch (reg->id) {
449 case KVM_REG_S390_TODPR:
450 r = put_user(vcpu->arch.sie_block->todpr,
451 (u32 __user *)reg->addr);
452 break;
453 case KVM_REG_S390_EPOCHDIFF:
454 r = put_user(vcpu->arch.sie_block->epoch,
455 (u64 __user *)reg->addr);
456 break;
457 case KVM_REG_S390_CPU_TIMER:
458 r = put_user(vcpu->arch.sie_block->cputm,
459 (u64 __user *)reg->addr);
460 break;
461 case KVM_REG_S390_CLOCK_COMP:
462 r = put_user(vcpu->arch.sie_block->ckc,
463 (u64 __user *)reg->addr);
464 break;
465 default:
466 break;
467 }
468
469 return r;
470}
471
472static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
473 struct kvm_one_reg *reg)
474{
475 int r = -EINVAL;
476
477 switch (reg->id) {
478 case KVM_REG_S390_TODPR:
479 r = get_user(vcpu->arch.sie_block->todpr,
480 (u32 __user *)reg->addr);
481 break;
482 case KVM_REG_S390_EPOCHDIFF:
483 r = get_user(vcpu->arch.sie_block->epoch,
484 (u64 __user *)reg->addr);
485 break;
486 case KVM_REG_S390_CPU_TIMER:
487 r = get_user(vcpu->arch.sie_block->cputm,
488 (u64 __user *)reg->addr);
489 break;
490 case KVM_REG_S390_CLOCK_COMP:
491 r = get_user(vcpu->arch.sie_block->ckc,
492 (u64 __user *)reg->addr);
493 break;
494 default:
495 break;
496 }
497
498 return r;
499}
500
426static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu) 501static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
427{ 502{
428 kvm_s390_vcpu_initial_reset(vcpu); 503 kvm_s390_vcpu_initial_reset(vcpu);
@@ -753,6 +828,18 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
753 case KVM_S390_INITIAL_RESET: 828 case KVM_S390_INITIAL_RESET:
754 r = kvm_arch_vcpu_ioctl_initial_reset(vcpu); 829 r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
755 break; 830 break;
831 case KVM_SET_ONE_REG:
832 case KVM_GET_ONE_REG: {
833 struct kvm_one_reg reg;
834 r = -EFAULT;
835 if (copy_from_user(&reg, argp, sizeof(reg)))
836 break;
837 if (ioctl == KVM_SET_ONE_REG)
838 r = kvm_arch_vcpu_ioctl_set_one_reg(vcpu, &reg);
839 else
840 r = kvm_arch_vcpu_ioctl_get_one_reg(vcpu, &reg);
841 break;
842 }
756#ifdef CONFIG_KVM_S390_UCONTROL 843#ifdef CONFIG_KVM_S390_UCONTROL
757 case KVM_S390_UCAS_MAP: { 844 case KVM_S390_UCAS_MAP: {
758 struct kvm_s390_ucas_mapping ucasmap; 845 struct kvm_s390_ucas_mapping ucasmap;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index ff28f9d1c9eb..2294377975e8 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -79,6 +79,7 @@ int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action);
79/* implemented in priv.c */ 79/* implemented in priv.c */
80int kvm_s390_handle_b2(struct kvm_vcpu *vcpu); 80int kvm_s390_handle_b2(struct kvm_vcpu *vcpu);
81int kvm_s390_handle_e5(struct kvm_vcpu *vcpu); 81int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
82int kvm_s390_handle_01(struct kvm_vcpu *vcpu);
82 83
83/* implemented in sigp.c */ 84/* implemented in sigp.c */
84int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); 85int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index e5a45dbd26ac..68a6b2ed16bf 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -380,3 +380,34 @@ int kvm_s390_handle_e5(struct kvm_vcpu *vcpu)
380 return -EOPNOTSUPP; 380 return -EOPNOTSUPP;
381} 381}
382 382
383static int handle_sckpf(struct kvm_vcpu *vcpu)
384{
385 u32 value;
386
387 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
388 return kvm_s390_inject_program_int(vcpu,
389 PGM_PRIVILEGED_OPERATION);
390
391 if (vcpu->run->s.regs.gprs[0] & 0x00000000ffff0000)
392 return kvm_s390_inject_program_int(vcpu,
393 PGM_SPECIFICATION);
394
395 value = vcpu->run->s.regs.gprs[0] & 0x000000000000ffff;
396 vcpu->arch.sie_block->todpr = value;
397
398 return 0;
399}
400
401static intercept_handler_t x01_handlers[256] = {
402 [0x07] = handle_sckpf,
403};
404
405int kvm_s390_handle_01(struct kvm_vcpu *vcpu)
406{
407 intercept_handler_t handler;
408
409 handler = x01_handlers[vcpu->arch.sie_block->ipa & 0x00ff];
410 if (handler)
411 return handler(vcpu);
412 return -EOPNOTSUPP;
413}