1 /* 2 * priv.c - handling privileged instructions 3 * 4 * Copyright IBM Corp. 2008 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License (version 2 only) 8 * as published by the Free Software Foundation. 9 * 10 * Author(s): Carsten Otte <cotte@de.ibm.com> 11 * Christian Borntraeger <borntraeger@de.ibm.com> 12 */ 13 14 #include <linux/kvm.h> 15 #include <linux/gfp.h> 16 #include <linux/errno.h> 17 #include <asm/current.h> 18 #include <asm/debug.h> 19 #include <asm/ebcdic.h> 20 #include <asm/sysinfo.h> 21 #include "gaccess.h" 22 #include "kvm-s390.h" 23 24 static int handle_set_prefix(struct kvm_vcpu *vcpu) 25 { 26 int base2 = vcpu->arch.sie_block->ipb >> 28; 27 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); 28 u64 operand2; 29 u32 address = 0; 30 u8 tmp; 31 32 vcpu->stat.instruction_spx++; 33 34 operand2 = disp2; 35 if (base2) 36 operand2 += vcpu->arch.guest_gprs[base2]; 37 38 /* must be word boundary */ 39 if (operand2 & 3) { 40 kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 41 goto out; 42 } 43 44 /* get the value */ 45 if (get_guest_u32(vcpu, operand2, &address)) { 46 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 47 goto out; 48 } 49 50 address = address & 0x7fffe000u; 51 52 /* make sure that the new value is valid memory */ 53 if (copy_from_guest_absolute(vcpu, &tmp, address, 1) || 54 (copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1))) { 55 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 56 goto out; 57 } 58 59 vcpu->arch.sie_block->prefix = address; 60 vcpu->arch.sie_block->ihcpu = 0xffff; 61 62 VCPU_EVENT(vcpu, 5, "setting prefix to %x", address); 63 out: 64 return 0; 65 } 66 67 static int handle_store_prefix(struct kvm_vcpu *vcpu) 68 { 69 int base2 = vcpu->arch.sie_block->ipb >> 28; 70 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); 71 u64 operand2; 72 u32 address; 73 74 vcpu->stat.instruction_stpx++; 75 operand2 = disp2; 76 if (base2) 77 operand2 += vcpu->arch.guest_gprs[base2]; 78 79 /* must be word boundary */ 80 if (operand2 & 3) { 81 kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 82 goto out; 83 } 84 85 address = vcpu->arch.sie_block->prefix; 86 address = address & 0x7fffe000u; 87 88 /* get the value */ 89 if (put_guest_u32(vcpu, operand2, address)) { 90 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 91 goto out; 92 } 93 94 VCPU_EVENT(vcpu, 5, "storing prefix to %x", address); 95 out: 96 return 0; 97 } 98 99 static int handle_store_cpu_address(struct kvm_vcpu *vcpu) 100 { 101 int base2 = vcpu->arch.sie_block->ipb >> 28; 102 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); 103 u64 useraddr; 104 int rc; 105 106 vcpu->stat.instruction_stap++; 107 useraddr = disp2; 108 if (base2) 109 useraddr += vcpu->arch.guest_gprs[base2]; 110 111 if (useraddr & 1) { 112 kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 113 goto out; 114 } 115 116 rc = put_guest_u16(vcpu, useraddr, vcpu->vcpu_id); 117 if (rc == -EFAULT) { 118 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 119 goto out; 120 } 121 122 VCPU_EVENT(vcpu, 5, "storing cpu address to %llx", useraddr); 123 out: 124 return 0; 125 } 126 127 static int handle_skey(struct kvm_vcpu *vcpu) 128 { 129 vcpu->stat.instruction_storage_key++; 130 vcpu->arch.sie_block->gpsw.addr -= 4; 131 VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation"); 132 return 0; 133 } 134 135 static int handle_stsch(struct kvm_vcpu *vcpu) 136 { 137 vcpu->stat.instruction_stsch++; 138 VCPU_EVENT(vcpu, 4, "%s", "store subchannel - CC3"); 139 /* condition code 3 */ 140 vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); 141 vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; 142 return 0; 143 } 144 145 static int handle_chsc(struct kvm_vcpu *vcpu) 146 { 147 vcpu->stat.instruction_chsc++; 148 VCPU_EVENT(vcpu, 4, "%s", "channel subsystem call - CC3"); 149 /* condition code 3 */ 150 vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); 151 vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; 152 return 0; 153 } 154 155 static int handle_stfl(struct kvm_vcpu *vcpu) 156 { 157 unsigned int facility_list = stfl(); 158 int rc; 159 160 vcpu->stat.instruction_stfl++; 161 /* only pass the facility bits, which we can handle */ 162 facility_list &= 0xff00fff3; 163 164 rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), 165 &facility_list, sizeof(facility_list)); 166 if (rc == -EFAULT) 167 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 168 else 169 VCPU_EVENT(vcpu, 5, "store facility list value %x", 170 facility_list); 171 return 0; 172 } 173 174 static int handle_stidp(struct kvm_vcpu *vcpu) 175 { 176 int base2 = vcpu->arch.sie_block->ipb >> 28; 177 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); 178 u64 operand2; 179 int rc; 180 181 vcpu->stat.instruction_stidp++; 182 operand2 = disp2; 183 if (base2) 184 operand2 += vcpu->arch.guest_gprs[base2]; 185 186 if (operand2 & 7) { 187 kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 188 goto out; 189 } 190 191 rc = put_guest_u64(vcpu, operand2, vcpu->arch.stidp_data); 192 if (rc == -EFAULT) { 193 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 194 goto out; 195 } 196 197 VCPU_EVENT(vcpu, 5, "%s", "store cpu id"); 198 out: 199 return 0; 200 } 201 202 static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem) 203 { 204 struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; 205 int cpus = 0; 206 int n; 207 208 spin_lock(&fi->lock); 209 for (n = 0; n < KVM_MAX_VCPUS; n++) 210 if (fi->local_int[n]) 211 cpus++; 212 spin_unlock(&fi->lock); 213 214 /* deal with other level 3 hypervisors */ 215 if (stsi(mem, 3, 2, 2) == -ENOSYS) 216 mem->count = 0; 217 if (mem->count < 8) 218 mem->count++; 219 for (n = mem->count - 1; n > 0 ; n--) 220 memcpy(&mem->vm[n], &mem->vm[n - 1], sizeof(mem->vm[0])); 221 222 mem->vm[0].cpus_total = cpus; 223 mem->vm[0].cpus_configured = cpus; 224 mem->vm[0].cpus_standby = 0; 225 mem->vm[0].cpus_reserved = 0; 226 mem->vm[0].caf = 1000; 227 memcpy(mem->vm[0].name, "KVMguest", 8); 228 ASCEBC(mem->vm[0].name, 8); 229 memcpy(mem->vm[0].cpi, "KVM/Linux ", 16); 230 ASCEBC(mem->vm[0].cpi, 16); 231 } 232 233 static int handle_stsi(struct kvm_vcpu *vcpu) 234 { 235 int fc = (vcpu->arch.guest_gprs[0] & 0xf0000000) >> 28; 236 int sel1 = vcpu->arch.guest_gprs[0] & 0xff; 237 int sel2 = vcpu->arch.guest_gprs[1] & 0xffff; 238 int base2 = vcpu->arch.sie_block->ipb >> 28; 239 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); 240 u64 operand2; 241 unsigned long mem; 242 243 vcpu->stat.instruction_stsi++; 244 VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2); 245 246 operand2 = disp2; 247 if (base2) 248 operand2 += vcpu->arch.guest_gprs[base2]; 249 250 if (operand2 & 0xfff && fc > 0) 251 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 252 253 switch (fc) { 254 case 0: 255 vcpu->arch.guest_gprs[0] = 3 << 28; 256 vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); 257 return 0; 258 case 1: /* same handling for 1 and 2 */ 259 case 2: 260 mem = get_zeroed_page(GFP_KERNEL); 261 if (!mem) 262 goto out_fail; 263 if (stsi((void *) mem, fc, sel1, sel2) == -ENOSYS) 264 goto out_mem; 265 break; 266 case 3: 267 if (sel1 != 2 || sel2 != 2) 268 goto out_fail; 269 mem = get_zeroed_page(GFP_KERNEL); 270 if (!mem) 271 goto out_fail; 272 handle_stsi_3_2_2(vcpu, (void *) mem); 273 break; 274 default: 275 goto out_fail; 276 } 277 278 if (copy_to_guest_absolute(vcpu, operand2, (void *) mem, PAGE_SIZE)) { 279 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 280 goto out_mem; 281 } 282 free_page(mem); 283 vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); 284 vcpu->arch.guest_gprs[0] = 0; 285 return 0; 286 out_mem: 287 free_page(mem); 288 out_fail: 289 /* condition code 3 */ 290 vcpu->arch.sie_block->gpsw.mask |= 3ul << 44; 291 return 0; 292 } 293 294 static intercept_handler_t priv_handlers[256] = { 295 [0x02] = handle_stidp, 296 [0x10] = handle_set_prefix, 297 [0x11] = handle_store_prefix, 298 [0x12] = handle_store_cpu_address, 299 [0x29] = handle_skey, 300 [0x2a] = handle_skey, 301 [0x2b] = handle_skey, 302 [0x34] = handle_stsch, 303 [0x5f] = handle_chsc, 304 [0x7d] = handle_stsi, 305 [0xb1] = handle_stfl, 306 }; 307 308 int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) 309 { 310 intercept_handler_t handler; 311 312 /* 313 * a lot of B2 instructions are priviledged. We first check for 314 * the priviledges ones, that we can handle in the kernel. If the 315 * kernel can handle this instruction, we check for the problem 316 * state bit and (a) handle the instruction or (b) send a code 2 317 * program check. 318 * Anything else goes to userspace.*/ 319 handler = priv_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; 320 if (handler) { 321 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) 322 return kvm_s390_inject_program_int(vcpu, 323 PGM_PRIVILEGED_OPERATION); 324 else 325 return handler(vcpu); 326 } 327 return -EOPNOTSUPP; 328 } 329