aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/intercept.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kvm/intercept.c')
-rw-r--r--arch/s390/kvm/intercept.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index f7b6df45d8b..02434543eab 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -105,6 +105,7 @@ static intercept_handler_t instruction_handlers[256] = {
105 [0xae] = kvm_s390_handle_sigp, 105 [0xae] = kvm_s390_handle_sigp,
106 [0xb2] = kvm_s390_handle_b2, 106 [0xb2] = kvm_s390_handle_b2,
107 [0xb7] = handle_lctl, 107 [0xb7] = handle_lctl,
108 [0xe5] = kvm_s390_handle_e5,
108 [0xeb] = handle_lctlg, 109 [0xeb] = handle_lctlg,
109}; 110};
110 111
@@ -131,7 +132,6 @@ static int handle_stop(struct kvm_vcpu *vcpu)
131 int rc = 0; 132 int rc = 0;
132 133
133 vcpu->stat.exit_stop_request++; 134 vcpu->stat.exit_stop_request++;
134 atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
135 spin_lock_bh(&vcpu->arch.local_int.lock); 135 spin_lock_bh(&vcpu->arch.local_int.lock);
136 if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) { 136 if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
137 vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP; 137 vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
@@ -148,6 +148,8 @@ static int handle_stop(struct kvm_vcpu *vcpu)
148 } 148 }
149 149
150 if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) { 150 if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
151 atomic_set_mask(CPUSTAT_STOPPED,
152 &vcpu->arch.sie_block->cpuflags);
151 vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP; 153 vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
152 VCPU_EVENT(vcpu, 3, "%s", "cpu stopped"); 154 VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
153 rc = -EOPNOTSUPP; 155 rc = -EOPNOTSUPP;
@@ -159,22 +161,42 @@ static int handle_stop(struct kvm_vcpu *vcpu)
159 161
160static int handle_validity(struct kvm_vcpu *vcpu) 162static int handle_validity(struct kvm_vcpu *vcpu)
161{ 163{
164 unsigned long vmaddr;
162 int viwhy = vcpu->arch.sie_block->ipb >> 16; 165 int viwhy = vcpu->arch.sie_block->ipb >> 16;
163 int rc; 166 int rc;
164 167
165 vcpu->stat.exit_validity++; 168 vcpu->stat.exit_validity++;
166 if ((viwhy == 0x37) && (vcpu->arch.sie_block->prefix 169 if (viwhy == 0x37) {
167 <= kvm_s390_vcpu_get_memsize(vcpu) - 2*PAGE_SIZE)) { 170 vmaddr = gmap_fault(vcpu->arch.sie_block->prefix,
168 rc = fault_in_pages_writeable((char __user *) 171 vcpu->arch.gmap);
169 vcpu->arch.sie_block->gmsor + 172 if (IS_ERR_VALUE(vmaddr)) {
170 vcpu->arch.sie_block->prefix, 173 rc = -EOPNOTSUPP;
171 2*PAGE_SIZE); 174 goto out;
172 if (rc) 175 }
176 rc = fault_in_pages_writeable((char __user *) vmaddr,
177 PAGE_SIZE);
178 if (rc) {
179 /* user will receive sigsegv, exit to user */
180 rc = -EOPNOTSUPP;
181 goto out;
182 }
183 vmaddr = gmap_fault(vcpu->arch.sie_block->prefix + PAGE_SIZE,
184 vcpu->arch.gmap);
185 if (IS_ERR_VALUE(vmaddr)) {
186 rc = -EOPNOTSUPP;
187 goto out;
188 }
189 rc = fault_in_pages_writeable((char __user *) vmaddr,
190 PAGE_SIZE);
191 if (rc) {
173 /* user will receive sigsegv, exit to user */ 192 /* user will receive sigsegv, exit to user */
174 rc = -EOPNOTSUPP; 193 rc = -EOPNOTSUPP;
194 goto out;
195 }
175 } else 196 } else
176 rc = -EOPNOTSUPP; 197 rc = -EOPNOTSUPP;
177 198
199out:
178 if (rc) 200 if (rc)
179 VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d", 201 VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
180 viwhy); 202 viwhy);