xref: /openbmc/qemu/hw/s390x/ipl.h (revision e17e57e862faf6e1f372385c18dcf6d3fd31158e)
1df75a4e2SFan Zhang /*
2df75a4e2SFan Zhang  * s390 IPL device
3df75a4e2SFan Zhang  *
4c3347ed0SJanosch Frank  * Copyright 2015, 2020 IBM Corp.
5df75a4e2SFan Zhang  * Author(s): Zhang Fan <bjfanzh@cn.ibm.com>
6c3347ed0SJanosch Frank  * Janosch Frank <frankja@linux.ibm.com>
7df75a4e2SFan Zhang  *
8df75a4e2SFan Zhang  * This work is licensed under the terms of the GNU GPL, version 2 or (at
9df75a4e2SFan Zhang  * your option) any later version. See the COPYING file in the top-level
10df75a4e2SFan Zhang  * directory.
11df75a4e2SFan Zhang  */
12df75a4e2SFan Zhang 
13df75a4e2SFan Zhang #ifndef HW_S390_IPL_H
14df75a4e2SFan Zhang #define HW_S390_IPL_H
15df75a4e2SFan Zhang 
16db3b2566SDavid Hildenbrand #include "cpu.h"
17fbc1384cSChristian Borntraeger #include "exec/address-spaces.h"
18a27bd6c7SMarkus Armbruster #include "hw/qdev-core.h"
19ba3658adSJared Rossi #include "hw/s390x/ipl/qipl.h"
20db1015e9SEduardo Habkost #include "qom/object.h"
21db3b2566SDavid Hildenbrand 
22bd1badf4SFarhan Ali #define DIAG308_FLAGS_LP_VALID 0x80
230927875eSJared Rossi #define MAX_BOOT_DEVS 8 /* Max number of devices that may have a bootindex */
24bd1badf4SFarhan Ali 
25bb185de4SJared Rossi void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp);
26bb185de4SJared Rossi void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp);
27*455e3bc3SJared Rossi void s390_rebuild_iplb(uint16_t index, IplParameterBlock *iplb);
28feacc6c2SDavid Hildenbrand void s390_ipl_update_diag308(IplParameterBlock *iplb);
297af51621SThomas Huth int s390_ipl_prepare_pv_header(Error **errp);
30c3347ed0SJanosch Frank int s390_ipl_pv_unpack(void);
31db3b2566SDavid Hildenbrand void s390_ipl_prepare_cpu(S390CPU *cpu);
32df75a4e2SFan Zhang IplParameterBlock *s390_ipl_get_iplb(void);
33c3347ed0SJanosch Frank IplParameterBlock *s390_ipl_get_iplb_pv(void);
34a30fb811SDavid Hildenbrand 
35a30fb811SDavid Hildenbrand enum s390_reset {
36a30fb811SDavid Hildenbrand     /* default is a reset not triggered by a CPU e.g. issued by QMP */
37a30fb811SDavid Hildenbrand     S390_RESET_EXTERNAL = 0,
38a30fb811SDavid Hildenbrand     S390_RESET_REIPL,
39a30fb811SDavid Hildenbrand     S390_RESET_MODIFIED_CLEAR,
40a30fb811SDavid Hildenbrand     S390_RESET_LOAD_NORMAL,
41c3347ed0SJanosch Frank     S390_RESET_PV,
42a30fb811SDavid Hildenbrand };
43a30fb811SDavid Hildenbrand void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type);
44a30fb811SDavid Hildenbrand void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type);
45a30fb811SDavid Hildenbrand void s390_ipl_clear_reset_request(void);
46df75a4e2SFan Zhang 
47118ee80fSCollin L. Walling #define QIPL_ADDRESS  0xcc
48118ee80fSCollin L. Walling 
4926b2a2a4SCollin L. Walling /* Boot Menu flags */
5026b2a2a4SCollin L. Walling #define QIPL_FLAG_BM_OPTS_CMD   0x80
5153b310ceSCollin L. Walling #define QIPL_FLAG_BM_OPTS_ZIPL  0x40
5226b2a2a4SCollin L. Walling 
5304fccf10SDavid Hildenbrand #define TYPE_S390_IPL "s390-ipl"
548063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(S390IPLState, S390_IPL)
5504fccf10SDavid Hildenbrand 
5604fccf10SDavid Hildenbrand struct S390IPLState {
5704fccf10SDavid Hildenbrand     /*< private >*/
5804fccf10SDavid Hildenbrand     DeviceState parent_obj;
593b8afb41SThomas Huth     IplParameterBlock iplb;
60c3347ed0SJanosch Frank     IplParameterBlock iplb_pv;
613b8afb41SThomas Huth     QemuIplParameters qipl;
6204fccf10SDavid Hildenbrand     uint64_t start_addr;
63bb099546SDavid Hildenbrand     uint64_t compat_start_addr;
6404fccf10SDavid Hildenbrand     uint64_t bios_start_addr;
65bb099546SDavid Hildenbrand     uint64_t compat_bios_start_addr;
6604fccf10SDavid Hildenbrand     bool enforce_bios;
6704fccf10SDavid Hildenbrand     bool iplb_valid;
68c3347ed0SJanosch Frank     bool iplb_valid_pv;
69*455e3bc3SJared Rossi     bool rebuilt_iplb;
70*455e3bc3SJared Rossi     uint16_t iplb_index;
71a30fb811SDavid Hildenbrand     /* reset related properties don't have to be migrated or reset */
72a30fb811SDavid Hildenbrand     enum s390_reset reset_type;
73a30fb811SDavid Hildenbrand     int reset_cpu_index;
7404fccf10SDavid Hildenbrand 
7504fccf10SDavid Hildenbrand     /*< public >*/
7604fccf10SDavid Hildenbrand     char *kernel;
7704fccf10SDavid Hildenbrand     char *initrd;
7804fccf10SDavid Hildenbrand     char *cmdline;
7904fccf10SDavid Hildenbrand     char *firmware;
8004fccf10SDavid Hildenbrand     uint8_t cssid;
8104fccf10SDavid Hildenbrand     uint8_t ssid;
8204fccf10SDavid Hildenbrand     uint16_t devno;
8304ca4b92SAlexander Yarygin     bool iplbext_migration;
8404fccf10SDavid Hildenbrand };
853b8afb41SThomas Huth QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong");
8604fccf10SDavid Hildenbrand 
879b39d294SJanosch Frank #define DIAG_308_RC_OK              0x0001
889b39d294SJanosch Frank #define DIAG_308_RC_NO_CONF         0x0102
899b39d294SJanosch Frank #define DIAG_308_RC_INVALID         0x0402
90c3347ed0SJanosch Frank #define DIAG_308_RC_NO_PV_CONF      0x0902
91c3347ed0SJanosch Frank #define DIAG_308_RC_INVAL_FOR_PV    0x0a02
929b39d294SJanosch Frank 
939b39d294SJanosch Frank #define DIAG308_RESET_MOD_CLR       0
949b39d294SJanosch Frank #define DIAG308_RESET_LOAD_NORM     1
959b39d294SJanosch Frank #define DIAG308_LOAD_CLEAR          3
969b39d294SJanosch Frank #define DIAG308_LOAD_NORMAL_DUMP    4
979b39d294SJanosch Frank #define DIAG308_SET                 5
989b39d294SJanosch Frank #define DIAG308_STORE               6
99c3347ed0SJanosch Frank #define DIAG308_PV_SET              8
100c3347ed0SJanosch Frank #define DIAG308_PV_STORE            9
101c3347ed0SJanosch Frank #define DIAG308_PV_START            10
1029b39d294SJanosch Frank 
1039946a911SAlexander Yarygin #define S390_IPL_TYPE_FCP 0x00
1049946a911SAlexander Yarygin #define S390_IPL_TYPE_CCW 0x02
105c3347ed0SJanosch Frank #define S390_IPL_TYPE_PV 0x05
106e468b673SAlexander Yarygin #define S390_IPL_TYPE_QEMU_SCSI 0xff
1079946a911SAlexander Yarygin 
1086aed9589SAlexander Yarygin #define S390_IPLB_HEADER_LEN 8
109c3347ed0SJanosch Frank #define S390_IPLB_MIN_PV_LEN 148
11004ca4b92SAlexander Yarygin #define S390_IPLB_MIN_CCW_LEN 200
1119946a911SAlexander Yarygin #define S390_IPLB_MIN_FCP_LEN 384
112e468b673SAlexander Yarygin #define S390_IPLB_MIN_QEMU_SCSI_LEN 200
1139946a911SAlexander Yarygin 
iplb_valid_len(IplParameterBlock * iplb)1149946a911SAlexander Yarygin static inline bool iplb_valid_len(IplParameterBlock *iplb)
1159946a911SAlexander Yarygin {
1169946a911SAlexander Yarygin     return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock);
1179946a911SAlexander Yarygin }
1189946a911SAlexander Yarygin 
ipl_valid_pv_components(IplParameterBlock * iplb)119c3347ed0SJanosch Frank static inline bool ipl_valid_pv_components(IplParameterBlock *iplb)
120c3347ed0SJanosch Frank {
121c3347ed0SJanosch Frank     IPLBlockPV *ipib_pv = &iplb->pv;
122c3347ed0SJanosch Frank     int i;
123c3347ed0SJanosch Frank 
124c3347ed0SJanosch Frank     if (ipib_pv->num_comp == 0) {
125c3347ed0SJanosch Frank         return false;
126c3347ed0SJanosch Frank     }
127c3347ed0SJanosch Frank 
128c3347ed0SJanosch Frank     for (i = 0; i < ipib_pv->num_comp; i++) {
129c3347ed0SJanosch Frank         /* Addr must be 4k aligned */
130c3347ed0SJanosch Frank         if (ipib_pv->components[i].addr & ~TARGET_PAGE_MASK) {
131c3347ed0SJanosch Frank             return false;
132c3347ed0SJanosch Frank         }
133c3347ed0SJanosch Frank 
134c3347ed0SJanosch Frank         /* Tweak prefix is monotonically increasing with each component */
135c3347ed0SJanosch Frank         if (i < ipib_pv->num_comp - 1 &&
136c3347ed0SJanosch Frank             ipib_pv->components[i].tweak_pref >=
137c3347ed0SJanosch Frank             ipib_pv->components[i + 1].tweak_pref) {
138c3347ed0SJanosch Frank             return false;
139c3347ed0SJanosch Frank         }
140c3347ed0SJanosch Frank     }
141c3347ed0SJanosch Frank     return true;
142c3347ed0SJanosch Frank }
143c3347ed0SJanosch Frank 
ipl_valid_pv_header(IplParameterBlock * iplb)144c3347ed0SJanosch Frank static inline bool ipl_valid_pv_header(IplParameterBlock *iplb)
145c3347ed0SJanosch Frank {
146c3347ed0SJanosch Frank         IPLBlockPV *ipib_pv = &iplb->pv;
147c3347ed0SJanosch Frank 
148c3347ed0SJanosch Frank         if (ipib_pv->pv_header_len > 2 * TARGET_PAGE_SIZE) {
149c3347ed0SJanosch Frank             return false;
150c3347ed0SJanosch Frank         }
151c3347ed0SJanosch Frank 
152c3347ed0SJanosch Frank         if (!address_space_access_valid(&address_space_memory,
153c3347ed0SJanosch Frank                                         ipib_pv->pv_header_addr,
154c3347ed0SJanosch Frank                                         ipib_pv->pv_header_len,
155c3347ed0SJanosch Frank                                         false,
156c3347ed0SJanosch Frank                                         MEMTXATTRS_UNSPECIFIED)) {
157c3347ed0SJanosch Frank             return false;
158c3347ed0SJanosch Frank         }
159c3347ed0SJanosch Frank 
160c3347ed0SJanosch Frank         return true;
161c3347ed0SJanosch Frank }
162c3347ed0SJanosch Frank 
iplb_valid_pv(IplParameterBlock * iplb)163c3347ed0SJanosch Frank static inline bool iplb_valid_pv(IplParameterBlock *iplb)
164c3347ed0SJanosch Frank {
165c3347ed0SJanosch Frank     if (iplb->pbt != S390_IPL_TYPE_PV ||
166c3347ed0SJanosch Frank         be32_to_cpu(iplb->len) < S390_IPLB_MIN_PV_LEN) {
167c3347ed0SJanosch Frank         return false;
168c3347ed0SJanosch Frank     }
169c3347ed0SJanosch Frank     if (!ipl_valid_pv_header(iplb)) {
170c3347ed0SJanosch Frank         return false;
171c3347ed0SJanosch Frank     }
172c3347ed0SJanosch Frank     return ipl_valid_pv_components(iplb);
173c3347ed0SJanosch Frank }
174c3347ed0SJanosch Frank 
iplb_valid(IplParameterBlock * iplb)17594c21436SJanosch Frank static inline bool iplb_valid(IplParameterBlock *iplb)
1769946a911SAlexander Yarygin {
177*455e3bc3SJared Rossi     uint32_t len = be32_to_cpu(iplb->len);
178*455e3bc3SJared Rossi 
17994c21436SJanosch Frank     switch (iplb->pbt) {
18094c21436SJanosch Frank     case S390_IPL_TYPE_FCP:
181*455e3bc3SJared Rossi         return len >= S390_IPLB_MIN_FCP_LEN;
18294c21436SJanosch Frank     case S390_IPL_TYPE_CCW:
183*455e3bc3SJared Rossi         return len >= S390_IPLB_MIN_CCW_LEN;
184*455e3bc3SJared Rossi     case S390_IPL_TYPE_QEMU_SCSI:
18594c21436SJanosch Frank     default:
18694c21436SJanosch Frank         return false;
1879946a911SAlexander Yarygin     }
1889946a911SAlexander Yarygin }
18904ca4b92SAlexander Yarygin 
190df75a4e2SFan Zhang #endif
191