]> git.proxmox.com Git - mirror_qemu.git/blame - hw/s390x/sclp.c
s390/sclp: add extended-length sccb support for kvm guest
[mirror_qemu.git] / hw / s390x / sclp.c
CommitLineData
f6c98f92
HG
1/*
2 * SCLP Support
3 *
4 * Copyright IBM, Corp. 2012
5 *
6 * Authors:
7 * Christian Borntraeger <borntraeger@de.ibm.com>
8 * Heinz Graalfs <graalfs@linux.vnet.ibm.com>
9 *
10 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
11 * option) any later version. See the COPYING file in the top-level directory.
12 *
13 */
14
9615495a 15#include "qemu/osdep.h"
393fc4c7 16#include "qemu/units.h"
da34e65c 17#include "qapi/error.h"
f6c98f92 18#include "cpu.h"
8cc3aecf 19#include "sysemu/sysemu.h"
311467f7 20#include "hw/boards.h"
83c9f4ca 21#include "hw/s390x/sclp.h"
477a72a1 22#include "hw/s390x/event-facility.h"
8cba80c3 23#include "hw/s390x/s390-pci-bus.h"
b038411d 24#include "hw/s390x/ipl.h"
f6c98f92 25
25a3c5af
DH
26static inline SCLPDevice *get_sclp_device(void)
27{
989fd865
CB
28 static SCLPDevice *sclp;
29
30 if (!sclp) {
31 sclp = SCLP(object_resolve_path_type("", TYPE_SCLP, NULL));
32 }
33 return sclp;
25a3c5af
DH
34}
35
0f73c5b3
JF
36static inline bool sclp_command_code_valid(uint32_t code)
37{
38 switch (code & SCLP_CMD_CODE_MASK) {
39 case SCLP_CMDW_READ_SCP_INFO:
40 case SCLP_CMDW_READ_SCP_INFO_FORCED:
41 case SCLP_CMDW_READ_CPU_INFO:
42 case SCLP_CMDW_CONFIGURE_IOA:
43 case SCLP_CMDW_DECONFIGURE_IOA:
44 case SCLP_CMD_READ_EVENT_DATA:
45 case SCLP_CMD_WRITE_EVENT_DATA:
46 case SCLP_CMD_WRITE_EVENT_MASK:
47 return true;
48 }
49 return false;
50}
51
1ecd6078
CW
52static bool sccb_verify_boundary(uint64_t sccb_addr, uint16_t sccb_len,
53 uint32_t code)
db13387c
CW
54{
55 uint64_t sccb_max_addr = sccb_addr + sccb_len - 1;
56 uint64_t sccb_boundary = (sccb_addr & PAGE_MASK) + PAGE_SIZE;
57
1ecd6078
CW
58 switch (code & SCLP_CMD_CODE_MASK) {
59 case SCLP_CMDW_READ_SCP_INFO:
60 case SCLP_CMDW_READ_SCP_INFO_FORCED:
61 case SCLP_CMDW_READ_CPU_INFO:
62 /*
63 * An extended-length SCCB is only allowed for Read SCP/CPU Info and
64 * is allowed to exceed the 4k boundary. The respective commands will
65 * set the length field to the required length if an insufficient
66 * SCCB length is provided.
67 */
68 if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
69 return true;
70 }
71 /* fallthrough */
72 default:
73 if (sccb_max_addr < sccb_boundary) {
74 return true;
75 }
db13387c
CW
76 }
77
78 return false;
79}
80
912d70d2 81static void prepare_cpu_entries(MachineState *ms, CPUEntry *entry, int *count)
026546e6 82{
4dd4200e 83 uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
026546e6
DH
84 int i;
85
4dd4200e 86 s390_get_feat_block(S390_FEAT_TYPE_SCLP_CPU, features);
bb535bb6
DH
87 for (i = 0, *count = 0; i < ms->possible_cpus->len; i++) {
88 if (!ms->possible_cpus->cpus[i].cpu) {
89 continue;
90 }
91 entry[*count].address = ms->possible_cpus->cpus[i].arch_id;
92 entry[*count].type = 0;
93 memcpy(entry[*count].features, features, sizeof(features));
94 (*count)++;
026546e6
DH
95 }
96}
97
0260b978
CW
98#define SCCB_REQ_LEN(s, max_cpus) (sizeof(s) + max_cpus * sizeof(CPUEntry))
99
1ecd6078
CW
100static inline bool ext_len_sccb_supported(SCCBHeader header)
101{
102 return s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) &&
103 header.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE;
104}
105
f6c98f92 106/* Provide information about the configuration, CPUs and storage */
25a3c5af 107static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
f6c98f92
HG
108{
109 ReadInfo *read_info = (ReadInfo *) sccb;
311467f7 110 MachineState *machine = MACHINE(qdev_get_machine());
bb535bb6 111 int cpu_count;
1def6656 112 int rnsize, rnmax;
b038411d 113 IplParameterBlock *ipib = s390_ipl_get_iplb();
0260b978 114 int required_len = SCCB_REQ_LEN(ReadInfo, machine->possible_cpus->len);
1ecd6078
CW
115 int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ?
116 offsetof(ReadInfo, entries) :
117 SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET;
1a7a5688 118 CPUEntry *entries_start = (void *)sccb + offset_cpu;
0260b978
CW
119
120 if (be16_to_cpu(sccb->h.length) < required_len) {
1ecd6078
CW
121 if (ext_len_sccb_supported(sccb->h)) {
122 sccb->h.length = cpu_to_be16(required_len);
123 }
0260b978
CW
124 sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
125 return;
126 }
8cc3aecf 127
8cc3aecf 128 /* CPU information */
1a7a5688 129 prepare_cpu_entries(machine, entries_start, &cpu_count);
8cc3aecf 130 read_info->entries_cpu = cpu_to_be16(cpu_count);
1a7a5688 131 read_info->offset_cpu = cpu_to_be16(offset_cpu);
ae71ed86 132 read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
8cc3aecf 133
059be520
DH
134 read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
135
4dd4200e
DH
136 /* Configuration Characteristic (Extension) */
137 s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR,
138 read_info->conf_char);
139 s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
140 read_info->conf_char_ext);
141
8cba80c3 142 read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
80b7a265 143 SCLP_HAS_IOA_RECONFIG);
f6c98f92 144
3fad3252 145 read_info->mha_pow = s390_get_mha_pow();
a3669307 146 read_info->hmfai = cpu_to_be32(s390_get_hmfai());
1def6656 147
71a2fd35 148 rnsize = 1 << (sclp->increment_size - 20);
1def6656
MR
149 if (rnsize <= 128) {
150 read_info->rnsize = rnsize;
151 } else {
152 read_info->rnsize = 0;
153 read_info->rnsize2 = cpu_to_be32(rnsize);
154 }
155
82fab5c5
DH
156 /* we don't support standby memory, maxram_size is never exposed */
157 rnmax = machine->ram_size >> sclp->increment_size;
1def6656
MR
158 if (rnmax < 0x10000) {
159 read_info->rnmax = cpu_to_be16(rnmax);
160 } else {
161 read_info->rnmax = cpu_to_be16(0);
162 read_info->rnmax2 = cpu_to_be64(rnmax);
163 }
164
b038411d
FA
165 if (ipib && ipib->flags & DIAG308_FLAGS_LP_VALID) {
166 memcpy(&read_info->loadparm, &ipib->loadparm,
167 sizeof(read_info->loadparm));
168 } else {
169 s390_ipl_set_loadparm(read_info->loadparm);
170 }
171
1def6656
MR
172 sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
173}
174
8cc3aecf 175/* Provide information about the CPU */
25a3c5af 176static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
8cc3aecf 177{
912d70d2 178 MachineState *machine = MACHINE(qdev_get_machine());
8cc3aecf 179 ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
bb535bb6 180 int cpu_count;
0260b978
CW
181 int required_len = SCCB_REQ_LEN(ReadCpuInfo, machine->possible_cpus->len);
182
183 if (be16_to_cpu(sccb->h.length) < required_len) {
1ecd6078
CW
184 if (ext_len_sccb_supported(sccb->h)) {
185 sccb->h.length = cpu_to_be16(required_len);
186 }
0260b978
CW
187 sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
188 return;
189 }
8cc3aecf 190
912d70d2 191 prepare_cpu_entries(machine, cpu_info->entries, &cpu_count);
8cc3aecf
JH
192 cpu_info->nr_configured = cpu_to_be16(cpu_count);
193 cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
194 cpu_info->nr_standby = cpu_to_be16(0);
195
196 /* The standby offset is 16-byte for each CPU */
197 cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
198 + cpu_info->nr_configured*sizeof(CPUEntry));
199
8cc3aecf
JH
200
201 sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
202}
203
80b7a265
CH
204static void sclp_configure_io_adapter(SCLPDevice *sclp, SCCB *sccb,
205 bool configure)
206{
207 int rc;
208
209 if (be16_to_cpu(sccb->h.length) < 16) {
210 rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
211 goto out_err;
212 }
213
214 switch (((IoaCfgSccb *)sccb)->atype) {
215 case SCLP_RECONFIG_PCI_ATYPE:
216 if (s390_has_feat(S390_FEAT_ZPCI)) {
217 if (configure) {
218 s390_pci_sclp_configure(sccb);
219 } else {
220 s390_pci_sclp_deconfigure(sccb);
221 }
222 return;
223 }
224 /* fallthrough */
225 default:
226 rc = SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED;
227 }
228
229 out_err:
230 sccb->h.response_code = cpu_to_be16(rc);
231}
232
25a3c5af 233static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
f6c98f92 234{
25a3c5af
DH
235 SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
236 SCLPEventFacility *ef = sclp->event_facility;
477a72a1 237 SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
559a17a1 238
5f04c14a 239 switch (code & SCLP_CMD_CODE_MASK) {
f6c98f92
HG
240 case SCLP_CMDW_READ_SCP_INFO:
241 case SCLP_CMDW_READ_SCP_INFO_FORCED:
25a3c5af 242 sclp_c->read_SCP_info(sclp, sccb);
f6c98f92 243 break;
8cc3aecf 244 case SCLP_CMDW_READ_CPU_INFO:
25a3c5af 245 sclp_c->read_cpu_info(sclp, sccb);
8cc3aecf 246 break;
80b7a265
CH
247 case SCLP_CMDW_CONFIGURE_IOA:
248 sclp_configure_io_adapter(sclp, sccb, true);
8cba80c3 249 break;
80b7a265
CH
250 case SCLP_CMDW_DECONFIGURE_IOA:
251 sclp_configure_io_adapter(sclp, sccb, false);
8cba80c3 252 break;
f6c98f92 253 default:
477a72a1 254 efc->command_handler(ef, sccb, code);
f6c98f92
HG
255 break;
256 }
257}
258
0f73c5b3
JF
259/*
260 * We only need the address to have something valid for the
261 * service_interrupt call.
262 */
263#define SCLP_PV_DUMMY_ADDR 0x4000
264int sclp_service_call_protected(CPUS390XState *env, uint64_t sccb,
265 uint32_t code)
266{
267 SCLPDevice *sclp = get_sclp_device();
268 SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
c1db53a5
CW
269 SCCBHeader header;
270 g_autofree SCCB *work_sccb = NULL;
0f73c5b3 271
c1db53a5
CW
272 s390_cpu_pv_mem_read(env_archcpu(env), 0, &header, sizeof(SCCBHeader));
273
274 work_sccb = g_malloc0(be16_to_cpu(header.length));
275 s390_cpu_pv_mem_read(env_archcpu(env), 0, work_sccb,
276 be16_to_cpu(header.length));
0f73c5b3
JF
277
278 if (!sclp_command_code_valid(code)) {
c1db53a5 279 work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
0f73c5b3
JF
280 goto out_write;
281 }
282
1ecd6078 283 if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length), code)) {
c1db53a5 284 work_sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
db13387c
CW
285 goto out_write;
286 }
287
c1db53a5 288 sclp_c->execute(sclp, work_sccb, code);
0f73c5b3 289out_write:
c1db53a5
CW
290 s390_cpu_pv_mem_write(env_archcpu(env), 0, work_sccb,
291 be16_to_cpu(work_sccb->h.length));
0f73c5b3
JF
292 sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR);
293 return 0;
294}
295
6e252802 296int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
f6c98f92 297{
25a3c5af
DH
298 SCLPDevice *sclp = get_sclp_device();
299 SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
c1db53a5
CW
300 SCCBHeader header;
301 g_autofree SCCB *work_sccb = NULL;
f6c98f92
HG
302
303 /* first some basic checks on program checks */
6e252802 304 if (env->psw.mask & PSW_MASK_PSTATE) {
e6de76fc 305 return -PGM_PRIVILEGED;
6e252802 306 }
f6c98f92 307 if (cpu_physical_memory_is_io(sccb)) {
e6de76fc 308 return -PGM_ADDRESSING;
f6c98f92 309 }
6e252802
TH
310 if ((sccb & ~0x1fffUL) == 0 || (sccb & ~0x1fffUL) == env->psa
311 || (sccb & ~0x7ffffff8UL) != 0) {
e6de76fc 312 return -PGM_SPECIFICATION;
f6c98f92
HG
313 }
314
c1db53a5
CW
315 /* the header contains the actual length of the sccb */
316 cpu_physical_memory_read(sccb, &header, sizeof(SCCBHeader));
317
318 /* Valid sccb sizes */
319 if (be16_to_cpu(header.length) < sizeof(SCCBHeader)) {
320 return -PGM_SPECIFICATION;
321 }
322
f6c98f92
HG
323 /*
324 * we want to work on a private copy of the sccb, to prevent guests
325 * from playing dirty tricks by modifying the memory content after
326 * the host has checked the values
327 */
c1db53a5
CW
328 work_sccb = g_malloc0(be16_to_cpu(header.length));
329 cpu_physical_memory_read(sccb, work_sccb, be16_to_cpu(header.length));
f6c98f92 330
0f73c5b3 331 if (!sclp_command_code_valid(code)) {
c1db53a5 332 work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
679b8447
JF
333 goto out_write;
334 }
f6c98f92 335
1ecd6078 336 if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length), code)) {
c1db53a5 337 work_sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
6f6c9333
JF
338 goto out_write;
339 }
340
c1db53a5 341 sclp_c->execute(sclp, work_sccb, code);
679b8447 342out_write:
c1db53a5
CW
343 cpu_physical_memory_write(sccb, work_sccb,
344 be16_to_cpu(work_sccb->h.length));
f6c98f92 345
1723a1b6 346 sclp_c->service_interrupt(sclp, sccb);
f6c98f92 347
e6de76fc 348 return 0;
f6c98f92
HG
349}
350
1723a1b6 351static void service_interrupt(SCLPDevice *sclp, uint32_t sccb)
f6c98f92 352{
1723a1b6 353 SCLPEventFacility *ef = sclp->event_facility;
477a72a1
HG
354 SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
355
559a17a1
HG
356 uint32_t param = sccb & ~3;
357
358 /* Indicate whether an event is still pending */
477a72a1 359 param |= efc->event_pending(ef) ? 1 : 0;
559a17a1
HG
360
361 if (!param) {
362 /* No need to send an interrupt, there's nothing to be notified about */
363 return;
364 }
365 s390_sclp_extint(param);
f6c98f92
HG
366}
367
1723a1b6
DH
368void sclp_service_interrupt(uint32_t sccb)
369{
370 SCLPDevice *sclp = get_sclp_device();
371 SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
372
373 sclp_c->service_interrupt(sclp, sccb);
374}
375
f6c98f92
HG
376/* qemu object creation and initialization functions */
377
559a17a1
HG
378void s390_sclp_init(void)
379{
515190d9 380 Object *new = object_new(TYPE_SCLP);
559a17a1 381
d2623129 382 object_property_add_child(qdev_get_machine(), TYPE_SCLP, new);
688ffbb4 383 object_unref(new);
ce189ab2 384 qdev_realize(DEVICE(new), NULL, &error_fatal);
559a17a1 385}
0844df77 386
515190d9
DH
387static void sclp_realize(DeviceState *dev, Error **errp)
388{
1cf065fb 389 MachineState *machine = MACHINE(qdev_get_machine());
515190d9 390 SCLPDevice *sclp = SCLP(dev);
1cf065fb
DH
391 uint64_t hw_limit;
392 int ret;
515190d9 393
8b638c43
DH
394 /*
395 * qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long
396 * as we can't find a fitting bus via the qom tree, we have to add the
397 * event facility to the sysbus, so e.g. a sclp console can be created.
398 */
992861fb
MA
399 if (!sysbus_realize(SYS_BUS_DEVICE(sclp->event_facility), errp)) {
400 return;
68424112 401 }
1cf065fb
DH
402
403 ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
404 if (ret == -E2BIG) {
992861fb 405 error_setg(errp, "host supports a maximum of %" PRIu64 " GB",
393fc4c7 406 hw_limit / GiB);
1cf065fb 407 } else if (ret) {
992861fb 408 error_setg(errp, "setting the guest size failed");
1cf065fb 409 }
515190d9
DH
410}
411
1cf065fb
DH
412static void sclp_memory_init(SCLPDevice *sclp)
413{
414 MachineState *machine = MACHINE(qdev_get_machine());
5c30ef93 415 MachineClass *machine_class = MACHINE_GET_CLASS(qdev_get_machine());
1cf065fb 416 ram_addr_t initial_mem = machine->ram_size;
1cf065fb
DH
417 int increment_size = 20;
418
419 /* The storage increment size is a multiple of 1M and is a power of 2.
5c30ef93
CB
420 * For some machine types, the number of storage increments must be
421 * MAX_STORAGE_INCREMENTS or fewer.
1cf065fb
DH
422 * The variable 'increment_size' is an exponent of 2 that can be
423 * used to calculate the size (in bytes) of an increment. */
5c30ef93
CB
424 while (machine_class->fixup_ram_size != NULL &&
425 (initial_mem >> increment_size) > MAX_STORAGE_INCREMENTS) {
1cf065fb
DH
426 increment_size++;
427 }
71a2fd35 428 sclp->increment_size = increment_size;
1cf065fb
DH
429}
430
515190d9
DH
431static void sclp_init(Object *obj)
432{
433 SCLPDevice *sclp = SCLP(obj);
434 Object *new;
435
436 new = object_new(TYPE_SCLP_EVENT_FACILITY);
d2623129 437 object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new);
515190d9
DH
438 object_unref(new);
439 sclp->event_facility = EVENT_FACILITY(new);
1cf065fb
DH
440
441 sclp_memory_init(sclp);
515190d9
DH
442}
443
444static void sclp_class_init(ObjectClass *oc, void *data)
445{
25a3c5af 446 SCLPDeviceClass *sc = SCLP_CLASS(oc);
515190d9
DH
447 DeviceClass *dc = DEVICE_CLASS(oc);
448
449 dc->desc = "SCLP (Service-Call Logical Processor)";
450 dc->realize = sclp_realize;
451 dc->hotpluggable = false;
452 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
e6cb60bf
TH
453 /*
454 * Reason: Creates TYPE_SCLP_EVENT_FACILITY in sclp_init
455 * which is a non-pluggable sysbus device
456 */
457 dc->user_creatable = false;
25a3c5af
DH
458
459 sc->read_SCP_info = read_SCP_info;
25a3c5af
DH
460 sc->read_cpu_info = sclp_read_cpu_info;
461 sc->execute = sclp_execute;
1723a1b6 462 sc->service_interrupt = service_interrupt;
515190d9
DH
463}
464
465static TypeInfo sclp_info = {
466 .name = TYPE_SCLP,
467 .parent = TYPE_DEVICE,
468 .instance_init = sclp_init,
469 .instance_size = sizeof(SCLPDevice),
470 .class_init = sclp_class_init,
471 .class_size = sizeof(SCLPDeviceClass),
472};
473
0844df77
MR
474static void register_types(void)
475{
515190d9 476 type_register_static(&sclp_info);
0844df77
MR
477}
478type_init(register_types);