1ef1df130SThomas Huth /* 2ef1df130SThomas Huth * S390x machine definitions and functions 3ef1df130SThomas Huth * 427e84d4eSChristian Borntraeger * Copyright IBM Corp. 2014, 2018 5ef1df130SThomas Huth * 6ef1df130SThomas Huth * Authors: 7ef1df130SThomas Huth * Thomas Huth <thuth@linux.vnet.ibm.com> 8ef1df130SThomas Huth * Christian Borntraeger <borntraeger@de.ibm.com> 9ef1df130SThomas Huth * Jason J. Herne <jjherne@us.ibm.com> 10ef1df130SThomas Huth * 11ef1df130SThomas Huth * This work is free software; you can redistribute it and/or modify 12ef1df130SThomas Huth * it under the terms of the GNU General Public License as published 13ef1df130SThomas Huth * by the Free Software Foundation; either version 2 of the License, 14ef1df130SThomas Huth * or (at your option) any later version. 15ef1df130SThomas Huth */ 16ef1df130SThomas Huth 179615495aSPeter Maydell #include "qemu/osdep.h" 18ef1df130SThomas Huth #include "cpu.h" 194e58b838SDavid Hildenbrand #include "internal.h" 20f16bbb9bSDavid Hildenbrand #include "kvm_s390x.h" 21d6454270SMarkus Armbruster #include "migration/vmstate.h" 227c12f710SDavid Hildenbrand #include "tcg_s390x.h" 23ef1df130SThomas Huth #include "sysemu/kvm.h" 2414a48c1dSMarkus Armbruster #include "sysemu/tcg.h" 25ef1df130SThomas Huth 26ef1df130SThomas Huth static int cpu_post_load(void *opaque, int version_id) 27ef1df130SThomas Huth { 28ef1df130SThomas Huth S390CPU *cpu = opaque; 29ef1df130SThomas Huth 30ef1df130SThomas Huth /* 31ef1df130SThomas Huth * As the cpu state is pushed to kvm via kvm_set_mp_state rather 32ef1df130SThomas Huth * than via cpu_synchronize_state, we need update kvm here. 33ef1df130SThomas Huth */ 34ef1df130SThomas Huth if (kvm_enabled()) { 35ef1df130SThomas Huth kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state); 363cda44f7SJens Freimann return kvm_s390_vcpu_interrupt_post_load(cpu); 37ef1df130SThomas Huth } 38ef1df130SThomas Huth 397c12f710SDavid Hildenbrand if (tcg_enabled()) { 407c12f710SDavid Hildenbrand /* Rearm the CKC timer if necessary */ 417c12f710SDavid Hildenbrand tcg_s390_tod_updated(CPU(cpu), RUN_ON_CPU_NULL); 427c12f710SDavid Hildenbrand } 437c12f710SDavid Hildenbrand 44ef1df130SThomas Huth return 0; 45ef1df130SThomas Huth } 46303c681aSRichard Henderson 4744b1ff31SDr. David Alan Gilbert static int cpu_pre_save(void *opaque) 483cda44f7SJens Freimann { 493cda44f7SJens Freimann S390CPU *cpu = opaque; 503cda44f7SJens Freimann 513cda44f7SJens Freimann if (kvm_enabled()) { 523cda44f7SJens Freimann kvm_s390_vcpu_interrupt_pre_save(cpu); 533cda44f7SJens Freimann } 5444b1ff31SDr. David Alan Gilbert 5544b1ff31SDr. David Alan Gilbert return 0; 563cda44f7SJens Freimann } 57ef1df130SThomas Huth 585cd8cadaSJuan Quintela static inline bool fpu_needed(void *opaque) 595cd8cadaSJuan Quintela { 605cd8cadaSJuan Quintela /* This looks odd, but we might want to NOT transfer fprs in the future */ 615cd8cadaSJuan Quintela return true; 625cd8cadaSJuan Quintela } 635cd8cadaSJuan Quintela 6452c6cfb7SChristian Borntraeger static const VMStateDescription vmstate_fpu = { 6546c804deSDavid Hildenbrand .name = "cpu/fpu", 6646c804deSDavid Hildenbrand .version_id = 1, 6746c804deSDavid Hildenbrand .minimum_version_id = 1, 685cd8cadaSJuan Quintela .needed = fpu_needed, 69ef1df130SThomas Huth .fields = (VMStateField[]) { 704f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[0][0], S390CPU), 714f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[1][0], S390CPU), 724f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[2][0], S390CPU), 734f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[3][0], S390CPU), 744f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[4][0], S390CPU), 754f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[5][0], S390CPU), 764f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[6][0], S390CPU), 774f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[7][0], S390CPU), 784f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[8][0], S390CPU), 794f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[9][0], S390CPU), 804f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[10][0], S390CPU), 814f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[11][0], S390CPU), 824f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[12][0], S390CPU), 834f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[13][0], S390CPU), 844f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[14][0], S390CPU), 854f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[15][0], S390CPU), 8646c804deSDavid Hildenbrand VMSTATE_UINT32(env.fpc, S390CPU), 8746c804deSDavid Hildenbrand VMSTATE_END_OF_LIST() 8846c804deSDavid Hildenbrand } 8946c804deSDavid Hildenbrand }; 9046c804deSDavid Hildenbrand 91b01501dbSPaolo Bonzini static bool vregs_needed(void *opaque) 92b01501dbSPaolo Bonzini { 937c72ac49SDavid Hildenbrand return s390_has_feat(S390_FEAT_VECTOR); 94b01501dbSPaolo Bonzini } 95b01501dbSPaolo Bonzini 9652c6cfb7SChristian Borntraeger static const VMStateDescription vmstate_vregs = { 97b2ac0ff5SEric Farman .name = "cpu/vregs", 98b2ac0ff5SEric Farman .version_id = 1, 99b2ac0ff5SEric Farman .minimum_version_id = 1, 1005cd8cadaSJuan Quintela .needed = vregs_needed, 101b2ac0ff5SEric Farman .fields = (VMStateField[]) { 102b2ac0ff5SEric Farman /* vregs[0][0] -> vregs[15][0] and fregs are overlays */ 1034f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[16][0], S390CPU), 1044f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[17][0], S390CPU), 1054f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[18][0], S390CPU), 1064f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[19][0], S390CPU), 1074f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[20][0], S390CPU), 1084f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[21][0], S390CPU), 1094f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[22][0], S390CPU), 1104f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[23][0], S390CPU), 1114f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[24][0], S390CPU), 1124f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[25][0], S390CPU), 1134f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[26][0], S390CPU), 1144f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[27][0], S390CPU), 1154f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[28][0], S390CPU), 1164f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[29][0], S390CPU), 1174f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[30][0], S390CPU), 1184f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[31][0], S390CPU), 1194f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[0][1], S390CPU), 1204f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[1][1], S390CPU), 1214f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[2][1], S390CPU), 1224f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[3][1], S390CPU), 1234f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[4][1], S390CPU), 1244f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[5][1], S390CPU), 1254f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[6][1], S390CPU), 1264f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[7][1], S390CPU), 1274f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[8][1], S390CPU), 1284f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[9][1], S390CPU), 1294f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[10][1], S390CPU), 1304f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[11][1], S390CPU), 1314f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[12][1], S390CPU), 1324f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[13][1], S390CPU), 1334f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[14][1], S390CPU), 1344f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[15][1], S390CPU), 1354f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[16][1], S390CPU), 1364f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[17][1], S390CPU), 1374f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[18][1], S390CPU), 1384f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[19][1], S390CPU), 1394f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[20][1], S390CPU), 1404f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[21][1], S390CPU), 1414f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[22][1], S390CPU), 1424f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[23][1], S390CPU), 1434f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[24][1], S390CPU), 1444f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[25][1], S390CPU), 1454f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[26][1], S390CPU), 1464f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[27][1], S390CPU), 1474f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[28][1], S390CPU), 1484f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[29][1], S390CPU), 1494f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[30][1], S390CPU), 1504f83d7d2SDavid Hildenbrand VMSTATE_UINT64(env.vregs[31][1], S390CPU), 151b2ac0ff5SEric Farman VMSTATE_END_OF_LIST() 152b2ac0ff5SEric Farman } 153b2ac0ff5SEric Farman }; 154b2ac0ff5SEric Farman 155b01501dbSPaolo Bonzini static bool riccb_needed(void *opaque) 156b01501dbSPaolo Bonzini { 1577c72ac49SDavid Hildenbrand return s390_has_feat(S390_FEAT_RUNTIME_INSTRUMENTATION); 158b01501dbSPaolo Bonzini } 159b01501dbSPaolo Bonzini 1609700230bSFan Zhang const VMStateDescription vmstate_riccb = { 1619700230bSFan Zhang .name = "cpu/riccb", 1629700230bSFan Zhang .version_id = 1, 1639700230bSFan Zhang .minimum_version_id = 1, 1649700230bSFan Zhang .needed = riccb_needed, 1659700230bSFan Zhang .fields = (VMStateField[]) { 1669700230bSFan Zhang VMSTATE_UINT8_ARRAY(env.riccb, S390CPU, 64), 1679700230bSFan Zhang VMSTATE_END_OF_LIST() 1689700230bSFan Zhang } 1699700230bSFan Zhang }; 1709700230bSFan Zhang 171303c681aSRichard Henderson static bool exval_needed(void *opaque) 172303c681aSRichard Henderson { 173303c681aSRichard Henderson S390CPU *cpu = opaque; 174303c681aSRichard Henderson return cpu->env.ex_value != 0; 175303c681aSRichard Henderson } 176303c681aSRichard Henderson 177303c681aSRichard Henderson const VMStateDescription vmstate_exval = { 178303c681aSRichard Henderson .name = "cpu/exval", 179303c681aSRichard Henderson .version_id = 1, 180303c681aSRichard Henderson .minimum_version_id = 1, 181303c681aSRichard Henderson .needed = exval_needed, 182303c681aSRichard Henderson .fields = (VMStateField[]) { 183303c681aSRichard Henderson VMSTATE_UINT64(env.ex_value, S390CPU), 184303c681aSRichard Henderson VMSTATE_END_OF_LIST() 185303c681aSRichard Henderson } 186303c681aSRichard Henderson }; 187303c681aSRichard Henderson 18862deb62dSFan Zhang static bool gscb_needed(void *opaque) 18962deb62dSFan Zhang { 1900280b3ebSChristian Borntraeger return s390_has_feat(S390_FEAT_GUARDED_STORAGE); 19162deb62dSFan Zhang } 19262deb62dSFan Zhang 19362deb62dSFan Zhang const VMStateDescription vmstate_gscb = { 19462deb62dSFan Zhang .name = "cpu/gscb", 19562deb62dSFan Zhang .version_id = 1, 19662deb62dSFan Zhang .minimum_version_id = 1, 19762deb62dSFan Zhang .needed = gscb_needed, 19862deb62dSFan Zhang .fields = (VMStateField[]) { 19962deb62dSFan Zhang VMSTATE_UINT64_ARRAY(env.gscb, S390CPU, 4), 20062deb62dSFan Zhang VMSTATE_END_OF_LIST() 20162deb62dSFan Zhang } 20262deb62dSFan Zhang }; 20362deb62dSFan Zhang 204b073c875SChristian Borntraeger static bool bpbc_needed(void *opaque) 205b073c875SChristian Borntraeger { 206b073c875SChristian Borntraeger return s390_has_feat(S390_FEAT_BPB); 207b073c875SChristian Borntraeger } 208b073c875SChristian Borntraeger 209b073c875SChristian Borntraeger const VMStateDescription vmstate_bpbc = { 210b073c875SChristian Borntraeger .name = "cpu/bpbc", 211b073c875SChristian Borntraeger .version_id = 1, 212b073c875SChristian Borntraeger .minimum_version_id = 1, 213b073c875SChristian Borntraeger .needed = bpbc_needed, 214b073c875SChristian Borntraeger .fields = (VMStateField[]) { 215b073c875SChristian Borntraeger VMSTATE_BOOL(env.bpbc, S390CPU), 216b073c875SChristian Borntraeger VMSTATE_END_OF_LIST() 217b073c875SChristian Borntraeger } 218b073c875SChristian Borntraeger }; 219b073c875SChristian Borntraeger 22027e84d4eSChristian Borntraeger static bool etoken_needed(void *opaque) 22127e84d4eSChristian Borntraeger { 22227e84d4eSChristian Borntraeger return s390_has_feat(S390_FEAT_ETOKEN); 22327e84d4eSChristian Borntraeger } 22427e84d4eSChristian Borntraeger 22527e84d4eSChristian Borntraeger const VMStateDescription vmstate_etoken = { 22627e84d4eSChristian Borntraeger .name = "cpu/etoken", 22727e84d4eSChristian Borntraeger .version_id = 1, 22827e84d4eSChristian Borntraeger .minimum_version_id = 1, 22927e84d4eSChristian Borntraeger .needed = etoken_needed, 23027e84d4eSChristian Borntraeger .fields = (VMStateField[]) { 23127e84d4eSChristian Borntraeger VMSTATE_UINT64(env.etoken, S390CPU), 23227e84d4eSChristian Borntraeger VMSTATE_UINT64(env.etoken_extension, S390CPU), 23327e84d4eSChristian Borntraeger VMSTATE_END_OF_LIST() 23427e84d4eSChristian Borntraeger } 23527e84d4eSChristian Borntraeger }; 23627e84d4eSChristian Borntraeger 237*fabdada9SCollin Walling static bool diag318_needed(void *opaque) 238*fabdada9SCollin Walling { 239*fabdada9SCollin Walling return s390_has_feat(S390_FEAT_DIAG_318); 240*fabdada9SCollin Walling } 241*fabdada9SCollin Walling 242*fabdada9SCollin Walling const VMStateDescription vmstate_diag318 = { 243*fabdada9SCollin Walling .name = "cpu/diag318", 244*fabdada9SCollin Walling .version_id = 1, 245*fabdada9SCollin Walling .minimum_version_id = 1, 246*fabdada9SCollin Walling .needed = diag318_needed, 247*fabdada9SCollin Walling .fields = (VMStateField[]) { 248*fabdada9SCollin Walling VMSTATE_UINT64(env.diag318_info, S390CPU), 249*fabdada9SCollin Walling VMSTATE_END_OF_LIST() 250*fabdada9SCollin Walling } 251*fabdada9SCollin Walling }; 252*fabdada9SCollin Walling 25346c804deSDavid Hildenbrand const VMStateDescription vmstate_s390_cpu = { 25446c804deSDavid Hildenbrand .name = "cpu", 25546c804deSDavid Hildenbrand .post_load = cpu_post_load, 2563cda44f7SJens Freimann .pre_save = cpu_pre_save, 2573cda44f7SJens Freimann .version_id = 4, 25846c804deSDavid Hildenbrand .minimum_version_id = 3, 25946c804deSDavid Hildenbrand .fields = (VMStateField[]) { 260ef1df130SThomas Huth VMSTATE_UINT64_ARRAY(env.regs, S390CPU, 16), 261ef1df130SThomas Huth VMSTATE_UINT64(env.psw.mask, S390CPU), 262ef1df130SThomas Huth VMSTATE_UINT64(env.psw.addr, S390CPU), 263ef1df130SThomas Huth VMSTATE_UINT64(env.psa, S390CPU), 264ef1df130SThomas Huth VMSTATE_UINT32(env.todpr, S390CPU), 265ef1df130SThomas Huth VMSTATE_UINT64(env.pfault_token, S390CPU), 266ef1df130SThomas Huth VMSTATE_UINT64(env.pfault_compare, S390CPU), 267ef1df130SThomas Huth VMSTATE_UINT64(env.pfault_select, S390CPU), 268ef1df130SThomas Huth VMSTATE_UINT64(env.cputm, S390CPU), 269ef1df130SThomas Huth VMSTATE_UINT64(env.ckc, S390CPU), 270ef1df130SThomas Huth VMSTATE_UINT64(env.gbea, S390CPU), 271ef1df130SThomas Huth VMSTATE_UINT64(env.pp, S390CPU), 272ef1df130SThomas Huth VMSTATE_UINT32_ARRAY(env.aregs, S390CPU, 16), 273ef1df130SThomas Huth VMSTATE_UINT64_ARRAY(env.cregs, S390CPU, 16), 274ef1df130SThomas Huth VMSTATE_UINT8(env.cpu_state, S390CPU), 27518ff9494SDavid Hildenbrand VMSTATE_UINT8(env.sigp_order, S390CPU), 2763cda44f7SJens Freimann VMSTATE_UINT32_V(irqstate_saved_size, S390CPU, 4), 27759046ec2SHalil Pasic VMSTATE_VBUFFER_UINT32(irqstate, S390CPU, 4, NULL, 2783cda44f7SJens Freimann irqstate_saved_size), 279ef1df130SThomas Huth VMSTATE_END_OF_LIST() 280ef1df130SThomas Huth }, 2815cd8cadaSJuan Quintela .subsections = (const VMStateDescription*[]) { 2825cd8cadaSJuan Quintela &vmstate_fpu, 2835cd8cadaSJuan Quintela &vmstate_vregs, 2849700230bSFan Zhang &vmstate_riccb, 285303c681aSRichard Henderson &vmstate_exval, 28662deb62dSFan Zhang &vmstate_gscb, 287b073c875SChristian Borntraeger &vmstate_bpbc, 28827e84d4eSChristian Borntraeger &vmstate_etoken, 289*fabdada9SCollin Walling &vmstate_diag318, 2905cd8cadaSJuan Quintela NULL 29146c804deSDavid Hildenbrand }, 292ef1df130SThomas Huth }; 293