1 /* 2 * S390x machine definitions and functions 3 * 4 * Copyright IBM Corp. 2014, 2018 5 * 6 * Authors: 7 * Thomas Huth <thuth@linux.vnet.ibm.com> 8 * Christian Borntraeger <borntraeger@de.ibm.com> 9 * Jason J. Herne <jjherne@us.ibm.com> 10 * 11 * This work is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published 13 * by the Free Software Foundation; either version 2 of the License, 14 * or (at your option) any later version. 15 */ 16 17 #include "qemu/osdep.h" 18 #include "cpu.h" 19 #include "s390x-internal.h" 20 #include "kvm/kvm_s390x.h" 21 #include "migration/vmstate.h" 22 #include "tcg/tcg_s390x.h" 23 #include "sysemu/kvm.h" 24 #include "sysemu/tcg.h" 25 26 static int cpu_post_load(void *opaque, int version_id) 27 { 28 S390CPU *cpu = opaque; 29 30 /* 31 * As the cpu state is pushed to kvm via kvm_set_mp_state rather 32 * than via cpu_synchronize_state, we need update kvm here. 33 */ 34 if (kvm_enabled()) { 35 kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state); 36 return kvm_s390_vcpu_interrupt_post_load(cpu); 37 } 38 39 if (tcg_enabled()) { 40 /* Rearm the CKC timer if necessary */ 41 tcg_s390_tod_updated(CPU(cpu), RUN_ON_CPU_NULL); 42 } 43 44 return 0; 45 } 46 47 static int cpu_pre_save(void *opaque) 48 { 49 S390CPU *cpu = opaque; 50 51 if (kvm_enabled()) { 52 kvm_s390_vcpu_interrupt_pre_save(cpu); 53 } 54 55 return 0; 56 } 57 58 static inline bool fpu_needed(void *opaque) 59 { 60 /* This looks odd, but we might want to NOT transfer fprs in the future */ 61 return true; 62 } 63 64 static const VMStateDescription vmstate_fpu = { 65 .name = "cpu/fpu", 66 .version_id = 1, 67 .minimum_version_id = 1, 68 .needed = fpu_needed, 69 .fields = (VMStateField[]) { 70 VMSTATE_UINT64(env.vregs[0][0], S390CPU), 71 VMSTATE_UINT64(env.vregs[1][0], S390CPU), 72 VMSTATE_UINT64(env.vregs[2][0], S390CPU), 73 VMSTATE_UINT64(env.vregs[3][0], S390CPU), 74 VMSTATE_UINT64(env.vregs[4][0], S390CPU), 75 VMSTATE_UINT64(env.vregs[5][0], S390CPU), 76 VMSTATE_UINT64(env.vregs[6][0], S390CPU), 77 VMSTATE_UINT64(env.vregs[7][0], S390CPU), 78 VMSTATE_UINT64(env.vregs[8][0], S390CPU), 79 VMSTATE_UINT64(env.vregs[9][0], S390CPU), 80 VMSTATE_UINT64(env.vregs[10][0], S390CPU), 81 VMSTATE_UINT64(env.vregs[11][0], S390CPU), 82 VMSTATE_UINT64(env.vregs[12][0], S390CPU), 83 VMSTATE_UINT64(env.vregs[13][0], S390CPU), 84 VMSTATE_UINT64(env.vregs[14][0], S390CPU), 85 VMSTATE_UINT64(env.vregs[15][0], S390CPU), 86 VMSTATE_UINT32(env.fpc, S390CPU), 87 VMSTATE_END_OF_LIST() 88 } 89 }; 90 91 static bool vregs_needed(void *opaque) 92 { 93 return s390_has_feat(S390_FEAT_VECTOR); 94 } 95 96 static const VMStateDescription vmstate_vregs = { 97 .name = "cpu/vregs", 98 .version_id = 1, 99 .minimum_version_id = 1, 100 .needed = vregs_needed, 101 .fields = (VMStateField[]) { 102 /* vregs[0][0] -> vregs[15][0] and fregs are overlays */ 103 VMSTATE_UINT64(env.vregs[16][0], S390CPU), 104 VMSTATE_UINT64(env.vregs[17][0], S390CPU), 105 VMSTATE_UINT64(env.vregs[18][0], S390CPU), 106 VMSTATE_UINT64(env.vregs[19][0], S390CPU), 107 VMSTATE_UINT64(env.vregs[20][0], S390CPU), 108 VMSTATE_UINT64(env.vregs[21][0], S390CPU), 109 VMSTATE_UINT64(env.vregs[22][0], S390CPU), 110 VMSTATE_UINT64(env.vregs[23][0], S390CPU), 111 VMSTATE_UINT64(env.vregs[24][0], S390CPU), 112 VMSTATE_UINT64(env.vregs[25][0], S390CPU), 113 VMSTATE_UINT64(env.vregs[26][0], S390CPU), 114 VMSTATE_UINT64(env.vregs[27][0], S390CPU), 115 VMSTATE_UINT64(env.vregs[28][0], S390CPU), 116 VMSTATE_UINT64(env.vregs[29][0], S390CPU), 117 VMSTATE_UINT64(env.vregs[30][0], S390CPU), 118 VMSTATE_UINT64(env.vregs[31][0], S390CPU), 119 VMSTATE_UINT64(env.vregs[0][1], S390CPU), 120 VMSTATE_UINT64(env.vregs[1][1], S390CPU), 121 VMSTATE_UINT64(env.vregs[2][1], S390CPU), 122 VMSTATE_UINT64(env.vregs[3][1], S390CPU), 123 VMSTATE_UINT64(env.vregs[4][1], S390CPU), 124 VMSTATE_UINT64(env.vregs[5][1], S390CPU), 125 VMSTATE_UINT64(env.vregs[6][1], S390CPU), 126 VMSTATE_UINT64(env.vregs[7][1], S390CPU), 127 VMSTATE_UINT64(env.vregs[8][1], S390CPU), 128 VMSTATE_UINT64(env.vregs[9][1], S390CPU), 129 VMSTATE_UINT64(env.vregs[10][1], S390CPU), 130 VMSTATE_UINT64(env.vregs[11][1], S390CPU), 131 VMSTATE_UINT64(env.vregs[12][1], S390CPU), 132 VMSTATE_UINT64(env.vregs[13][1], S390CPU), 133 VMSTATE_UINT64(env.vregs[14][1], S390CPU), 134 VMSTATE_UINT64(env.vregs[15][1], S390CPU), 135 VMSTATE_UINT64(env.vregs[16][1], S390CPU), 136 VMSTATE_UINT64(env.vregs[17][1], S390CPU), 137 VMSTATE_UINT64(env.vregs[18][1], S390CPU), 138 VMSTATE_UINT64(env.vregs[19][1], S390CPU), 139 VMSTATE_UINT64(env.vregs[20][1], S390CPU), 140 VMSTATE_UINT64(env.vregs[21][1], S390CPU), 141 VMSTATE_UINT64(env.vregs[22][1], S390CPU), 142 VMSTATE_UINT64(env.vregs[23][1], S390CPU), 143 VMSTATE_UINT64(env.vregs[24][1], S390CPU), 144 VMSTATE_UINT64(env.vregs[25][1], S390CPU), 145 VMSTATE_UINT64(env.vregs[26][1], S390CPU), 146 VMSTATE_UINT64(env.vregs[27][1], S390CPU), 147 VMSTATE_UINT64(env.vregs[28][1], S390CPU), 148 VMSTATE_UINT64(env.vregs[29][1], S390CPU), 149 VMSTATE_UINT64(env.vregs[30][1], S390CPU), 150 VMSTATE_UINT64(env.vregs[31][1], S390CPU), 151 VMSTATE_END_OF_LIST() 152 } 153 }; 154 155 static bool riccb_needed(void *opaque) 156 { 157 return s390_has_feat(S390_FEAT_RUNTIME_INSTRUMENTATION); 158 } 159 160 const VMStateDescription vmstate_riccb = { 161 .name = "cpu/riccb", 162 .version_id = 1, 163 .minimum_version_id = 1, 164 .needed = riccb_needed, 165 .fields = (VMStateField[]) { 166 VMSTATE_UINT8_ARRAY(env.riccb, S390CPU, 64), 167 VMSTATE_END_OF_LIST() 168 } 169 }; 170 171 static bool exval_needed(void *opaque) 172 { 173 S390CPU *cpu = opaque; 174 return cpu->env.ex_value != 0; 175 } 176 177 const VMStateDescription vmstate_exval = { 178 .name = "cpu/exval", 179 .version_id = 1, 180 .minimum_version_id = 1, 181 .needed = exval_needed, 182 .fields = (VMStateField[]) { 183 VMSTATE_UINT64(env.ex_value, S390CPU), 184 VMSTATE_END_OF_LIST() 185 } 186 }; 187 188 static bool gscb_needed(void *opaque) 189 { 190 return s390_has_feat(S390_FEAT_GUARDED_STORAGE); 191 } 192 193 const VMStateDescription vmstate_gscb = { 194 .name = "cpu/gscb", 195 .version_id = 1, 196 .minimum_version_id = 1, 197 .needed = gscb_needed, 198 .fields = (VMStateField[]) { 199 VMSTATE_UINT64_ARRAY(env.gscb, S390CPU, 4), 200 VMSTATE_END_OF_LIST() 201 } 202 }; 203 204 static bool bpbc_needed(void *opaque) 205 { 206 return s390_has_feat(S390_FEAT_BPB); 207 } 208 209 const VMStateDescription vmstate_bpbc = { 210 .name = "cpu/bpbc", 211 .version_id = 1, 212 .minimum_version_id = 1, 213 .needed = bpbc_needed, 214 .fields = (VMStateField[]) { 215 VMSTATE_BOOL(env.bpbc, S390CPU), 216 VMSTATE_END_OF_LIST() 217 } 218 }; 219 220 static bool etoken_needed(void *opaque) 221 { 222 return s390_has_feat(S390_FEAT_ETOKEN); 223 } 224 225 const VMStateDescription vmstate_etoken = { 226 .name = "cpu/etoken", 227 .version_id = 1, 228 .minimum_version_id = 1, 229 .needed = etoken_needed, 230 .fields = (VMStateField[]) { 231 VMSTATE_UINT64(env.etoken, S390CPU), 232 VMSTATE_UINT64(env.etoken_extension, S390CPU), 233 VMSTATE_END_OF_LIST() 234 } 235 }; 236 237 static bool diag318_needed(void *opaque) 238 { 239 return s390_has_feat(S390_FEAT_DIAG_318); 240 } 241 242 const VMStateDescription vmstate_diag318 = { 243 .name = "cpu/diag318", 244 .version_id = 1, 245 .minimum_version_id = 1, 246 .needed = diag318_needed, 247 .fields = (VMStateField[]) { 248 VMSTATE_UINT64(env.diag318_info, S390CPU), 249 VMSTATE_END_OF_LIST() 250 } 251 }; 252 253 const VMStateDescription vmstate_s390_cpu = { 254 .name = "cpu", 255 .post_load = cpu_post_load, 256 .pre_save = cpu_pre_save, 257 .version_id = 4, 258 .minimum_version_id = 3, 259 .fields = (VMStateField[]) { 260 VMSTATE_UINT64_ARRAY(env.regs, S390CPU, 16), 261 VMSTATE_UINT64(env.psw.mask, S390CPU), 262 VMSTATE_UINT64(env.psw.addr, S390CPU), 263 VMSTATE_UINT64(env.psa, S390CPU), 264 VMSTATE_UINT32(env.todpr, S390CPU), 265 VMSTATE_UINT64(env.pfault_token, S390CPU), 266 VMSTATE_UINT64(env.pfault_compare, S390CPU), 267 VMSTATE_UINT64(env.pfault_select, S390CPU), 268 VMSTATE_UINT64(env.cputm, S390CPU), 269 VMSTATE_UINT64(env.ckc, S390CPU), 270 VMSTATE_UINT64(env.gbea, S390CPU), 271 VMSTATE_UINT64(env.pp, S390CPU), 272 VMSTATE_UINT32_ARRAY(env.aregs, S390CPU, 16), 273 VMSTATE_UINT64_ARRAY(env.cregs, S390CPU, 16), 274 VMSTATE_UINT8(env.cpu_state, S390CPU), 275 VMSTATE_UINT8(env.sigp_order, S390CPU), 276 VMSTATE_UINT32_V(irqstate_saved_size, S390CPU, 4), 277 VMSTATE_VBUFFER_UINT32(irqstate, S390CPU, 4, NULL, 278 irqstate_saved_size), 279 VMSTATE_END_OF_LIST() 280 }, 281 .subsections = (const VMStateDescription*[]) { 282 &vmstate_fpu, 283 &vmstate_vregs, 284 &vmstate_riccb, 285 &vmstate_exval, 286 &vmstate_gscb, 287 &vmstate_bpbc, 288 &vmstate_etoken, 289 &vmstate_diag318, 290 NULL 291 }, 292 }; 293