1 /* 2 * handling diagnose instructions 3 * 4 * Copyright IBM Corp. 2008, 2011 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/kvm_host.h> 16 #include <asm/pgalloc.h> 17 #include <asm/virtio-ccw.h> 18 #include "kvm-s390.h" 19 #include "trace.h" 20 #include "trace-s390.h" 21 #include "gaccess.h" 22 23 static int diag_release_pages(struct kvm_vcpu *vcpu) 24 { 25 unsigned long start, end; 26 unsigned long prefix = vcpu->arch.sie_block->prefix; 27 28 start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; 29 end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096; 30 31 if (start & ~PAGE_MASK || end & ~PAGE_MASK || start > end 32 || start < 2 * PAGE_SIZE) 33 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 34 35 VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end); 36 vcpu->stat.diagnose_10++; 37 38 /* we checked for start > end above */ 39 if (end < prefix || start >= prefix + 2 * PAGE_SIZE) { 40 gmap_discard(start, end, vcpu->arch.gmap); 41 } else { 42 if (start < prefix) 43 gmap_discard(start, prefix, vcpu->arch.gmap); 44 if (end >= prefix) 45 gmap_discard(prefix + 2 * PAGE_SIZE, 46 end, vcpu->arch.gmap); 47 } 48 return 0; 49 } 50 51 static int __diag_page_ref_service(struct kvm_vcpu *vcpu) 52 { 53 struct prs_parm { 54 u16 code; 55 u16 subcode; 56 u16 parm_len; 57 u16 parm_version; 58 u64 token_addr; 59 u64 select_mask; 60 u64 compare_mask; 61 u64 zarch; 62 }; 63 struct prs_parm parm; 64 int rc; 65 u16 rx = (vcpu->arch.sie_block->ipa & 0xf0) >> 4; 66 u16 ry = (vcpu->arch.sie_block->ipa & 0x0f); 67 unsigned long hva_token = KVM_HVA_ERR_BAD; 68 69 if (vcpu->run->s.regs.gprs[rx] & 7) 70 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 71 if (copy_from_guest(vcpu, &parm, vcpu->run->s.regs.gprs[rx], sizeof(parm))) 72 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 73 if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258) 74 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 75 76 switch (parm.subcode) { 77 case 0: /* TOKEN */ 78 if (vcpu->arch.pfault_token != KVM_S390_PFAULT_TOKEN_INVALID) { 79 /* 80 * If the pagefault handshake is already activated, 81 * the token must not be changed. We have to return 82 * decimal 8 instead, as mandated in SC24-6084. 83 */ 84 vcpu->run->s.regs.gprs[ry] = 8; 85 return 0; 86 } 87 88 if ((parm.compare_mask & parm.select_mask) != parm.compare_mask || 89 parm.token_addr & 7 || parm.zarch != 0x8000000000000000ULL) 90 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 91 92 hva_token = gfn_to_hva(vcpu->kvm, gpa_to_gfn(parm.token_addr)); 93 if (kvm_is_error_hva(hva_token)) 94 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 95 96 vcpu->arch.pfault_token = parm.token_addr; 97 vcpu->arch.pfault_select = parm.select_mask; 98 vcpu->arch.pfault_compare = parm.compare_mask; 99 vcpu->run->s.regs.gprs[ry] = 0; 100 rc = 0; 101 break; 102 case 1: /* 103 * CANCEL 104 * Specification allows to let already pending tokens survive 105 * the cancel, therefore to reduce code complexity, we assume 106 * all outstanding tokens are already pending. 107 */ 108 if (parm.token_addr || parm.select_mask || 109 parm.compare_mask || parm.zarch) 110 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 111 112 vcpu->run->s.regs.gprs[ry] = 0; 113 /* 114 * If the pfault handling was not established or is already 115 * canceled SC24-6084 requests to return decimal 4. 116 */ 117 if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) 118 vcpu->run->s.regs.gprs[ry] = 4; 119 else 120 vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID; 121 122 rc = 0; 123 break; 124 default: 125 rc = -EOPNOTSUPP; 126 break; 127 } 128 129 return rc; 130 } 131 132 static int __diag_time_slice_end(struct kvm_vcpu *vcpu) 133 { 134 VCPU_EVENT(vcpu, 5, "%s", "diag time slice end"); 135 vcpu->stat.diagnose_44++; 136 kvm_vcpu_on_spin(vcpu); 137 return 0; 138 } 139 140 static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu) 141 { 142 struct kvm *kvm = vcpu->kvm; 143 struct kvm_vcpu *tcpu; 144 int tid; 145 int i; 146 147 tid = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; 148 vcpu->stat.diagnose_9c++; 149 VCPU_EVENT(vcpu, 5, "diag time slice end directed to %d", tid); 150 151 if (tid == vcpu->vcpu_id) 152 return 0; 153 154 kvm_for_each_vcpu(i, tcpu, kvm) 155 if (tcpu->vcpu_id == tid) { 156 kvm_vcpu_yield_to(tcpu); 157 break; 158 } 159 160 return 0; 161 } 162 163 static int __diag_ipl_functions(struct kvm_vcpu *vcpu) 164 { 165 unsigned int reg = vcpu->arch.sie_block->ipa & 0xf; 166 unsigned long subcode = vcpu->run->s.regs.gprs[reg] & 0xffff; 167 168 VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode); 169 switch (subcode) { 170 case 3: 171 vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR; 172 page_table_reset_pgste(current->mm, 0, TASK_SIZE); 173 break; 174 case 4: 175 vcpu->run->s390_reset_flags = 0; 176 page_table_reset_pgste(current->mm, 0, TASK_SIZE); 177 break; 178 default: 179 return -EOPNOTSUPP; 180 } 181 182 atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); 183 vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM; 184 vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL; 185 vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT; 186 vcpu->run->exit_reason = KVM_EXIT_S390_RESET; 187 VCPU_EVENT(vcpu, 3, "requesting userspace resets %llx", 188 vcpu->run->s390_reset_flags); 189 trace_kvm_s390_request_resets(vcpu->run->s390_reset_flags); 190 return -EREMOTE; 191 } 192 193 static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu) 194 { 195 int ret; 196 197 /* No virtio-ccw notification? Get out quickly. */ 198 if (!vcpu->kvm->arch.css_support || 199 (vcpu->run->s.regs.gprs[1] != KVM_S390_VIRTIO_CCW_NOTIFY)) 200 return -EOPNOTSUPP; 201 202 /* 203 * The layout is as follows: 204 * - gpr 2 contains the subchannel id (passed as addr) 205 * - gpr 3 contains the virtqueue index (passed as datamatch) 206 * - gpr 4 contains the index on the bus (optionally) 207 */ 208 ret = kvm_io_bus_write_cookie(vcpu->kvm, KVM_VIRTIO_CCW_NOTIFY_BUS, 209 vcpu->run->s.regs.gprs[2] & 0xffffffff, 210 8, &vcpu->run->s.regs.gprs[3], 211 vcpu->run->s.regs.gprs[4]); 212 213 /* 214 * Return cookie in gpr 2, but don't overwrite the register if the 215 * diagnose will be handled by userspace. 216 */ 217 if (ret != -EOPNOTSUPP) 218 vcpu->run->s.regs.gprs[2] = ret; 219 /* kvm_io_bus_write_cookie returns -EOPNOTSUPP if it found no match. */ 220 return ret < 0 ? ret : 0; 221 } 222 223 int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) 224 { 225 int code = kvm_s390_get_base_disp_rs(vcpu) & 0xffff; 226 227 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) 228 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); 229 230 trace_kvm_s390_handle_diag(vcpu, code); 231 switch (code) { 232 case 0x10: 233 return diag_release_pages(vcpu); 234 case 0x44: 235 return __diag_time_slice_end(vcpu); 236 case 0x9c: 237 return __diag_time_slice_end_directed(vcpu); 238 case 0x258: 239 return __diag_page_ref_service(vcpu); 240 case 0x308: 241 return __diag_ipl_functions(vcpu); 242 case 0x500: 243 return __diag_virtio_hypercall(vcpu); 244 default: 245 return -EOPNOTSUPP; 246 } 247 } 248