1 #include "qemu/osdep.h" 2 #include "cpu.h" 3 #include "qemu/timer.h" 4 5 #include "migration/cpu.h" 6 7 #ifdef TARGET_SPARC64 8 static const VMStateDescription vmstate_cpu_timer = { 9 .name = "cpu_timer", 10 .version_id = 1, 11 .minimum_version_id = 1, 12 .fields = (const VMStateField[]) { 13 VMSTATE_UINT32(frequency, CPUTimer), 14 VMSTATE_UINT32(disabled, CPUTimer), 15 VMSTATE_UINT64(disabled_mask, CPUTimer), 16 VMSTATE_UINT32(npt, CPUTimer), 17 VMSTATE_UINT64(npt_mask, CPUTimer), 18 VMSTATE_INT64(clock_offset, CPUTimer), 19 VMSTATE_TIMER_PTR(qtimer, CPUTimer), 20 VMSTATE_END_OF_LIST() 21 } 22 }; 23 24 #define VMSTATE_CPU_TIMER(_f, _s) \ 25 VMSTATE_STRUCT_POINTER(_f, _s, vmstate_cpu_timer, CPUTimer) 26 27 static const VMStateDescription vmstate_trap_state = { 28 .name = "trap_state", 29 .version_id = 1, 30 .minimum_version_id = 1, 31 .fields = (const VMStateField[]) { 32 VMSTATE_UINT64(tpc, trap_state), 33 VMSTATE_UINT64(tnpc, trap_state), 34 VMSTATE_UINT64(tstate, trap_state), 35 VMSTATE_UINT32(tt, trap_state), 36 VMSTATE_END_OF_LIST() 37 } 38 }; 39 40 static const VMStateDescription vmstate_tlb_entry = { 41 .name = "tlb_entry", 42 .version_id = 1, 43 .minimum_version_id = 1, 44 .fields = (const VMStateField[]) { 45 VMSTATE_UINT64(tag, SparcTLBEntry), 46 VMSTATE_UINT64(tte, SparcTLBEntry), 47 VMSTATE_END_OF_LIST() 48 } 49 }; 50 #endif 51 52 static int get_psr(QEMUFile *f, void *opaque, size_t size, 53 const VMStateField *field) 54 { 55 SPARCCPU *cpu = opaque; 56 CPUSPARCState *env = &cpu->env; 57 uint32_t val = qemu_get_be32(f); 58 59 /* needed to ensure that the wrapping registers are correctly updated */ 60 env->cwp = 0; 61 cpu_put_psr_raw(env, val); 62 63 return 0; 64 } 65 66 static int put_psr(QEMUFile *f, void *opaque, size_t size, 67 const VMStateField *field, JSONWriter *vmdesc) 68 { 69 SPARCCPU *cpu = opaque; 70 CPUSPARCState *env = &cpu->env; 71 uint32_t val; 72 73 val = cpu_get_psr(env); 74 75 qemu_put_be32(f, val); 76 return 0; 77 } 78 79 static const VMStateInfo vmstate_psr = { 80 .name = "psr", 81 .get = get_psr, 82 .put = put_psr, 83 }; 84 85 static int get_fsr(QEMUFile *f, void *opaque, size_t size, 86 const VMStateField *field) 87 { 88 SPARCCPU *cpu = opaque; 89 target_ulong val = qemu_get_betl(f); 90 91 cpu_put_fsr(&cpu->env, val); 92 return 0; 93 } 94 95 static int put_fsr(QEMUFile *f, void *opaque, size_t size, 96 const VMStateField *field, JSONWriter *vmdesc) 97 { 98 SPARCCPU *cpu = opaque; 99 target_ulong val = cpu_get_fsr(&cpu->env); 100 101 qemu_put_betl(f, val); 102 return 0; 103 } 104 105 static const VMStateInfo vmstate_fsr = { 106 .name = "fsr", 107 .get = get_fsr, 108 .put = put_fsr, 109 }; 110 111 #ifdef TARGET_SPARC64 112 static int get_xcc(QEMUFile *f, void *opaque, size_t size, 113 const VMStateField *field) 114 { 115 SPARCCPU *cpu = opaque; 116 CPUSPARCState *env = &cpu->env; 117 uint32_t val = qemu_get_be32(f); 118 119 /* Do not clobber icc.[NV] */ 120 env->cc_N = deposit64(env->cc_N, 32, 32, -(val & PSR_NEG)); 121 env->cc_V = deposit64(env->cc_V, 32, 32, -(val & PSR_OVF)); 122 env->xcc_Z = ~val & PSR_ZERO; 123 env->xcc_C = (val >> PSR_CARRY_SHIFT) & 1; 124 125 return 0; 126 } 127 128 static int put_xcc(QEMUFile *f, void *opaque, size_t size, 129 const VMStateField *field, JSONWriter *vmdesc) 130 { 131 SPARCCPU *cpu = opaque; 132 CPUSPARCState *env = &cpu->env; 133 uint32_t val = cpu_get_ccr(env); 134 135 /* Extract just xcc out of ccr and shift into legacy position. */ 136 qemu_put_be32(f, (val & 0xf0) << (20 - 4)); 137 return 0; 138 } 139 140 static const VMStateInfo vmstate_xcc = { 141 .name = "xcc", 142 .get = get_xcc, 143 .put = put_xcc, 144 }; 145 #else 146 static bool fq_needed(void *opaque) 147 { 148 SPARCCPU *cpu = opaque; 149 return cpu->env.fsr_qne; 150 } 151 152 static const VMStateDescription vmstate_fq = { 153 .name = "cpu/fq", 154 .version_id = 1, 155 .minimum_version_id = 1, 156 .needed = fq_needed, 157 .fields = (const VMStateField[]) { 158 VMSTATE_UINT32(env.fq.s.addr, SPARCCPU), 159 VMSTATE_UINT32(env.fq.s.insn, SPARCCPU), 160 VMSTATE_END_OF_LIST() 161 }, 162 }; 163 #endif 164 165 static int cpu_pre_save(void *opaque) 166 { 167 SPARCCPU *cpu = opaque; 168 CPUSPARCState *env = &cpu->env; 169 170 /* if env->cwp == env->nwindows - 1, this will set the ins of the last 171 * window as the outs of the first window 172 */ 173 cpu_set_cwp(env, env->cwp); 174 175 return 0; 176 } 177 178 /* 32-bit SPARC retains migration compatibility with older versions 179 * of QEMU; 64-bit SPARC has had a migration break since then, so the 180 * versions are different. 181 */ 182 #ifndef TARGET_SPARC64 183 #define SPARC_VMSTATE_VER 7 184 #else 185 #define SPARC_VMSTATE_VER 9 186 #endif 187 188 const VMStateDescription vmstate_sparc_cpu = { 189 .name = "cpu", 190 .version_id = SPARC_VMSTATE_VER, 191 .minimum_version_id = SPARC_VMSTATE_VER, 192 .pre_save = cpu_pre_save, 193 .fields = (const VMStateField[]) { 194 VMSTATE_UINTTL_ARRAY(env.gregs, SPARCCPU, 8), 195 VMSTATE_UINT32(env.nwindows, SPARCCPU), 196 VMSTATE_VARRAY_MULTIPLY(env.regbase, SPARCCPU, env.nwindows, 16, 197 vmstate_info_uinttl, target_ulong), 198 VMSTATE_CPUDOUBLE_ARRAY(env.fpr, SPARCCPU, TARGET_DPREGS), 199 VMSTATE_UINTTL(env.pc, SPARCCPU), 200 VMSTATE_UINTTL(env.npc, SPARCCPU), 201 VMSTATE_UINTTL(env.y, SPARCCPU), 202 { 203 .name = "psr", 204 .version_id = 0, 205 .size = sizeof(uint32_t), 206 .info = &vmstate_psr, 207 .flags = VMS_SINGLE, 208 .offset = 0, 209 }, 210 { 211 .name = "fsr", 212 .version_id = 0, 213 .size = sizeof(target_ulong), 214 .info = &vmstate_fsr, 215 .flags = VMS_SINGLE, 216 .offset = 0, 217 }, 218 VMSTATE_UINTTL(env.tbr, SPARCCPU), 219 VMSTATE_INT32(env.interrupt_index, SPARCCPU), 220 VMSTATE_UINT32(env.pil_in, SPARCCPU), 221 #ifndef TARGET_SPARC64 222 /* MMU */ 223 VMSTATE_UINT32(env.wim, SPARCCPU), 224 VMSTATE_UINT32_ARRAY(env.mmuregs, SPARCCPU, 32), 225 VMSTATE_UINT64_ARRAY(env.mxccdata, SPARCCPU, 4), 226 VMSTATE_UINT64_ARRAY(env.mxccregs, SPARCCPU, 8), 227 VMSTATE_UINT32(env.mmubpctrv, SPARCCPU), 228 VMSTATE_UINT32(env.mmubpctrc, SPARCCPU), 229 VMSTATE_UINT32(env.mmubpctrs, SPARCCPU), 230 VMSTATE_UINT64(env.mmubpaction, SPARCCPU), 231 VMSTATE_UINT64_ARRAY(env.mmubpregs, SPARCCPU, 4), 232 #else 233 VMSTATE_UINT64(env.lsu, SPARCCPU), 234 VMSTATE_UINT64_ARRAY(env.immu.mmuregs, SPARCCPU, 16), 235 VMSTATE_UINT64_ARRAY(env.dmmu.mmuregs, SPARCCPU, 16), 236 VMSTATE_STRUCT_ARRAY(env.itlb, SPARCCPU, 64, 0, 237 vmstate_tlb_entry, SparcTLBEntry), 238 VMSTATE_STRUCT_ARRAY(env.dtlb, SPARCCPU, 64, 0, 239 vmstate_tlb_entry, SparcTLBEntry), 240 VMSTATE_UINT32(env.mmu_version, SPARCCPU), 241 VMSTATE_STRUCT_ARRAY(env.ts, SPARCCPU, MAXTL_MAX, 0, 242 vmstate_trap_state, trap_state), 243 { 244 .name = "xcc", 245 .version_id = 0, 246 .size = sizeof(uint32_t), 247 .info = &vmstate_xcc, 248 .flags = VMS_SINGLE, 249 .offset = 0, 250 }, 251 VMSTATE_UINT32(env.asi, SPARCCPU), 252 VMSTATE_UINT32(env.pstate, SPARCCPU), 253 VMSTATE_UINT32(env.tl, SPARCCPU), 254 VMSTATE_UINT32(env.cansave, SPARCCPU), 255 VMSTATE_UINT32(env.canrestore, SPARCCPU), 256 VMSTATE_UINT32(env.otherwin, SPARCCPU), 257 VMSTATE_UINT32(env.wstate, SPARCCPU), 258 VMSTATE_UINT32(env.cleanwin, SPARCCPU), 259 VMSTATE_UINT64_ARRAY(env.agregs, SPARCCPU, 8), 260 VMSTATE_UINT64_ARRAY(env.bgregs, SPARCCPU, 8), 261 VMSTATE_UINT64_ARRAY(env.igregs, SPARCCPU, 8), 262 VMSTATE_UINT64_ARRAY(env.mgregs, SPARCCPU, 8), 263 VMSTATE_UNUSED(4), /* was unused high half of uint64_t fprs */ 264 VMSTATE_UINT32(env.fprs, SPARCCPU), 265 VMSTATE_UINT64(env.tick_cmpr, SPARCCPU), 266 VMSTATE_UINT64(env.stick_cmpr, SPARCCPU), 267 VMSTATE_CPU_TIMER(env.tick, SPARCCPU), 268 VMSTATE_CPU_TIMER(env.stick, SPARCCPU), 269 VMSTATE_UINT64(env.gsr, SPARCCPU), 270 VMSTATE_UINT32(env.gl, SPARCCPU), 271 VMSTATE_UINT64(env.hpstate, SPARCCPU), 272 VMSTATE_UINT64_ARRAY(env.htstate, SPARCCPU, MAXTL_MAX), 273 VMSTATE_UINT64(env.hintp, SPARCCPU), 274 VMSTATE_UINT64(env.htba, SPARCCPU), 275 VMSTATE_UINT64(env.hver, SPARCCPU), 276 VMSTATE_UINT64(env.hstick_cmpr, SPARCCPU), 277 VMSTATE_UINT64(env.ssr, SPARCCPU), 278 VMSTATE_CPU_TIMER(env.hstick, SPARCCPU), 279 /* On SPARC32 env.psrpil and env.cwp are migrated as part of the PSR */ 280 VMSTATE_UINT32(env.psrpil, SPARCCPU), 281 VMSTATE_UINT32(env.cwp, SPARCCPU), 282 #endif 283 VMSTATE_END_OF_LIST() 284 }, 285 #ifndef TARGET_SPARC64 286 .subsections = (const VMStateDescription * const []) { 287 &vmstate_fq, 288 NULL 289 }, 290 #endif 291 292 }; 293