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"
19b6b47223SCho, Yu-Chen #include "s390x-internal.h"
2067043607SCho, Yu-Chen #include "kvm/kvm_s390x.h"
21d6454270SMarkus Armbruster #include "migration/vmstate.h"
22c9274b6bSCho, Yu-Chen #include "tcg/tcg_s390x.h"
23*32cad1ffSPhilippe Mathieu-Daudé #include "system/kvm.h"
24*32cad1ffSPhilippe Mathieu-Daudé #include "system/tcg.h"
25ef1df130SThomas Huth
cpu_post_load(void * opaque,int version_id)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
cpu_pre_save(void * opaque)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
fpu_needed(void * opaque)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,
695c04ea96SRichard Henderson .fields = (const 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
vregs_needed(void * opaque)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,
1015c04ea96SRichard Henderson .fields = (const 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
riccb_needed(void * opaque)155b01501dbSPaolo Bonzini static bool riccb_needed(void *opaque)
156b01501dbSPaolo Bonzini {
1577c72ac49SDavid Hildenbrand return s390_has_feat(S390_FEAT_RUNTIME_INSTRUMENTATION);
158b01501dbSPaolo Bonzini }
159b01501dbSPaolo Bonzini
1605c04ea96SRichard Henderson static 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,
1655c04ea96SRichard Henderson .fields = (const VMStateField[]) {
1669700230bSFan Zhang VMSTATE_UINT8_ARRAY(env.riccb, S390CPU, 64),
1679700230bSFan Zhang VMSTATE_END_OF_LIST()
1689700230bSFan Zhang }
1699700230bSFan Zhang };
1709700230bSFan Zhang
exval_needed(void * opaque)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
1775c04ea96SRichard Henderson static 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,
1825c04ea96SRichard Henderson .fields = (const VMStateField[]) {
183303c681aSRichard Henderson VMSTATE_UINT64(env.ex_value, S390CPU),
184303c681aSRichard Henderson VMSTATE_END_OF_LIST()
185303c681aSRichard Henderson }
186303c681aSRichard Henderson };
187303c681aSRichard Henderson
gscb_needed(void * opaque)18862deb62dSFan Zhang static bool gscb_needed(void *opaque)
18962deb62dSFan Zhang {
1900280b3ebSChristian Borntraeger return s390_has_feat(S390_FEAT_GUARDED_STORAGE);
19162deb62dSFan Zhang }
19262deb62dSFan Zhang
1935c04ea96SRichard Henderson static 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,
1985c04ea96SRichard Henderson .fields = (const VMStateField[]) {
19962deb62dSFan Zhang VMSTATE_UINT64_ARRAY(env.gscb, S390CPU, 4),
20062deb62dSFan Zhang VMSTATE_END_OF_LIST()
20162deb62dSFan Zhang }
20262deb62dSFan Zhang };
20362deb62dSFan Zhang
bpbc_needed(void * opaque)204b073c875SChristian Borntraeger static bool bpbc_needed(void *opaque)
205b073c875SChristian Borntraeger {
206b073c875SChristian Borntraeger return s390_has_feat(S390_FEAT_BPB);
207b073c875SChristian Borntraeger }
208b073c875SChristian Borntraeger
2095c04ea96SRichard Henderson static 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,
2145c04ea96SRichard Henderson .fields = (const VMStateField[]) {
215b073c875SChristian Borntraeger VMSTATE_BOOL(env.bpbc, S390CPU),
216b073c875SChristian Borntraeger VMSTATE_END_OF_LIST()
217b073c875SChristian Borntraeger }
218b073c875SChristian Borntraeger };
219b073c875SChristian Borntraeger
etoken_needed(void * opaque)22027e84d4eSChristian Borntraeger static bool etoken_needed(void *opaque)
22127e84d4eSChristian Borntraeger {
22227e84d4eSChristian Borntraeger return s390_has_feat(S390_FEAT_ETOKEN);
22327e84d4eSChristian Borntraeger }
22427e84d4eSChristian Borntraeger
2255c04ea96SRichard Henderson static 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,
2305c04ea96SRichard Henderson .fields = (const 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
diag318_needed(void * opaque)237fabdada9SCollin Walling static bool diag318_needed(void *opaque)
238fabdada9SCollin Walling {
239fabdada9SCollin Walling return s390_has_feat(S390_FEAT_DIAG_318);
240fabdada9SCollin Walling }
241fabdada9SCollin Walling
2425c04ea96SRichard Henderson static const VMStateDescription vmstate_diag318 = {
243fabdada9SCollin Walling .name = "cpu/diag318",
244fabdada9SCollin Walling .version_id = 1,
245fabdada9SCollin Walling .minimum_version_id = 1,
246fabdada9SCollin Walling .needed = diag318_needed,
2475c04ea96SRichard Henderson .fields = (const VMStateField[]) {
248fabdada9SCollin Walling VMSTATE_UINT64(env.diag318_info, S390CPU),
249fabdada9SCollin Walling VMSTATE_END_OF_LIST()
250fabdada9SCollin Walling }
251fabdada9SCollin Walling };
252fabdada9SCollin 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,
2595c04ea96SRichard Henderson .fields = (const 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 },
2815c04ea96SRichard Henderson .subsections = (const VMStateDescription * const []) {
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,
289fabdada9SCollin Walling &vmstate_diag318,
2905cd8cadaSJuan Quintela NULL
29146c804deSDavid Hildenbrand },
292ef1df130SThomas Huth };
293