diff options
-rw-r--r-- | arch/s390/kvm/priv.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 6f9599416bae..2440602e6df1 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -30,6 +30,38 @@ | |||
30 | #include "kvm-s390.h" | 30 | #include "kvm-s390.h" |
31 | #include "trace.h" | 31 | #include "trace.h" |
32 | 32 | ||
33 | /* Handle SCK (SET CLOCK) interception */ | ||
34 | static int handle_set_clock(struct kvm_vcpu *vcpu) | ||
35 | { | ||
36 | struct kvm_vcpu *cpup; | ||
37 | s64 hostclk, val; | ||
38 | u64 op2; | ||
39 | int i; | ||
40 | |||
41 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
42 | return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); | ||
43 | |||
44 | op2 = kvm_s390_get_base_disp_s(vcpu); | ||
45 | if (op2 & 7) /* Operand must be on a doubleword boundary */ | ||
46 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
47 | if (get_guest(vcpu, val, (u64 __user *) op2)) | ||
48 | return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
49 | |||
50 | if (store_tod_clock(&hostclk)) { | ||
51 | kvm_s390_set_psw_cc(vcpu, 3); | ||
52 | return 0; | ||
53 | } | ||
54 | val = (val - hostclk) & ~0x3fUL; | ||
55 | |||
56 | mutex_lock(&vcpu->kvm->lock); | ||
57 | kvm_for_each_vcpu(i, cpup, vcpu->kvm) | ||
58 | cpup->arch.sie_block->epoch = val; | ||
59 | mutex_unlock(&vcpu->kvm->lock); | ||
60 | |||
61 | kvm_s390_set_psw_cc(vcpu, 0); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
33 | static int handle_set_prefix(struct kvm_vcpu *vcpu) | 65 | static int handle_set_prefix(struct kvm_vcpu *vcpu) |
34 | { | 66 | { |
35 | u64 operand2; | 67 | u64 operand2; |
@@ -465,6 +497,7 @@ out_exception: | |||
465 | 497 | ||
466 | static const intercept_handler_t b2_handlers[256] = { | 498 | static const intercept_handler_t b2_handlers[256] = { |
467 | [0x02] = handle_stidp, | 499 | [0x02] = handle_stidp, |
500 | [0x04] = handle_set_clock, | ||
468 | [0x10] = handle_set_prefix, | 501 | [0x10] = handle_set_prefix, |
469 | [0x11] = handle_store_prefix, | 502 | [0x11] = handle_store_prefix, |
470 | [0x12] = handle_store_cpu_address, | 503 | [0x12] = handle_store_cpu_address, |