diff options
Diffstat (limited to 'arch/s390/kvm/intercept.c')
-rw-r--r-- | arch/s390/kvm/intercept.c | 38 |
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 | ||
160 | static int handle_validity(struct kvm_vcpu *vcpu) | 162 | static 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 | ||
199 | out: | ||
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); |