aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/kvm/intercept.c85
-rw-r--r--arch/s390/kvm/kvm-s390.h3
-rw-r--r--arch/s390/kvm/priv.c78
3 files changed, 81 insertions, 85 deletions
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index f0b8be0cc08d..5ee56e5acc23 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -22,87 +22,6 @@
22#include "trace.h" 22#include "trace.h"
23#include "trace-s390.h" 23#include "trace-s390.h"
24 24
25static int handle_lctlg(struct kvm_vcpu *vcpu)
26{
27 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
28 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
29 u64 useraddr;
30 int reg, rc;
31
32 vcpu->stat.instruction_lctlg++;
33
34 useraddr = kvm_s390_get_base_disp_rsy(vcpu);
35
36 if (useraddr & 7)
37 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
38
39 reg = reg1;
40
41 VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3,
42 useraddr);
43 trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr);
44
45 do {
46 rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg],
47 (u64 __user *) useraddr);
48 if (rc)
49 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
50 useraddr += 8;
51 if (reg == reg3)
52 break;
53 reg = (reg + 1) % 16;
54 } while (1);
55 return 0;
56}
57
58static int handle_lctl(struct kvm_vcpu *vcpu)
59{
60 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
61 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
62 u64 useraddr;
63 u32 val = 0;
64 int reg, rc;
65
66 vcpu->stat.instruction_lctl++;
67
68 useraddr = kvm_s390_get_base_disp_rs(vcpu);
69
70 if (useraddr & 3)
71 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
72
73 VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3,
74 useraddr);
75 trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr);
76
77 reg = reg1;
78 do {
79 rc = get_guest(vcpu, val, (u32 __user *) useraddr);
80 if (rc)
81 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
82 vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul;
83 vcpu->arch.sie_block->gcr[reg] |= val;
84 useraddr += 4;
85 if (reg == reg3)
86 break;
87 reg = (reg + 1) % 16;
88 } while (1);
89 return 0;
90}
91
92static const intercept_handler_t eb_handlers[256] = {
93 [0x2f] = handle_lctlg,
94 [0x8a] = kvm_s390_handle_priv_eb,
95};
96
97static int handle_eb(struct kvm_vcpu *vcpu)
98{
99 intercept_handler_t handler;
100
101 handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff];
102 if (handler)
103 return handler(vcpu);
104 return -EOPNOTSUPP;
105}
106 25
107static const intercept_handler_t instruction_handlers[256] = { 26static const intercept_handler_t instruction_handlers[256] = {
108 [0x01] = kvm_s390_handle_01, 27 [0x01] = kvm_s390_handle_01,
@@ -110,10 +29,10 @@ static const intercept_handler_t instruction_handlers[256] = {
110 [0x83] = kvm_s390_handle_diag, 29 [0x83] = kvm_s390_handle_diag,
111 [0xae] = kvm_s390_handle_sigp, 30 [0xae] = kvm_s390_handle_sigp,
112 [0xb2] = kvm_s390_handle_b2, 31 [0xb2] = kvm_s390_handle_b2,
113 [0xb7] = handle_lctl, 32 [0xb7] = kvm_s390_handle_lctl,
114 [0xb9] = kvm_s390_handle_b9, 33 [0xb9] = kvm_s390_handle_b9,
115 [0xe5] = kvm_s390_handle_e5, 34 [0xe5] = kvm_s390_handle_e5,
116 [0xeb] = handle_eb, 35 [0xeb] = kvm_s390_handle_eb,
117}; 36};
118 37
119static int handle_noop(struct kvm_vcpu *vcpu) 38static int handle_noop(struct kvm_vcpu *vcpu)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 15795b8f8ff5..028ca9fd2158 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -132,7 +132,8 @@ int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
132int kvm_s390_handle_01(struct kvm_vcpu *vcpu); 132int kvm_s390_handle_01(struct kvm_vcpu *vcpu);
133int kvm_s390_handle_b9(struct kvm_vcpu *vcpu); 133int kvm_s390_handle_b9(struct kvm_vcpu *vcpu);
134int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); 134int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu);
135int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu); 135int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu);
136int kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
136 137
137/* implemented in sigp.c */ 138/* implemented in sigp.c */
138int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); 139int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 4b8fb6cc3c45..c7603f5b4c28 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -590,11 +590,87 @@ int kvm_s390_handle_b9(struct kvm_vcpu *vcpu)
590 return -EOPNOTSUPP; 590 return -EOPNOTSUPP;
591} 591}
592 592
593int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
594{
595 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
596 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
597 u64 useraddr;
598 u32 val = 0;
599 int reg, rc;
600
601 vcpu->stat.instruction_lctl++;
602
603 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
604 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
605
606 useraddr = kvm_s390_get_base_disp_rs(vcpu);
607
608 if (useraddr & 3)
609 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
610
611 VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3,
612 useraddr);
613 trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr);
614
615 reg = reg1;
616 do {
617 rc = get_guest(vcpu, val, (u32 __user *) useraddr);
618 if (rc)
619 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
620 vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul;
621 vcpu->arch.sie_block->gcr[reg] |= val;
622 useraddr += 4;
623 if (reg == reg3)
624 break;
625 reg = (reg + 1) % 16;
626 } while (1);
627
628 return 0;
629}
630
631static int handle_lctlg(struct kvm_vcpu *vcpu)
632{
633 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
634 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
635 u64 useraddr;
636 int reg, rc;
637
638 vcpu->stat.instruction_lctlg++;
639
640 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
641 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
642
643 useraddr = kvm_s390_get_base_disp_rsy(vcpu);
644
645 if (useraddr & 7)
646 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
647
648 reg = reg1;
649
650 VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3,
651 useraddr);
652 trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr);
653
654 do {
655 rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg],
656 (u64 __user *) useraddr);
657 if (rc)
658 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
659 useraddr += 8;
660 if (reg == reg3)
661 break;
662 reg = (reg + 1) % 16;
663 } while (1);
664
665 return 0;
666}
667
593static const intercept_handler_t eb_handlers[256] = { 668static const intercept_handler_t eb_handlers[256] = {
669 [0x2f] = handle_lctlg,
594 [0x8a] = handle_io_inst, 670 [0x8a] = handle_io_inst,
595}; 671};
596 672
597int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu) 673int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
598{ 674{
599 intercept_handler_t handler; 675 intercept_handler_t handler;
600 676