15
#include "qemu/osdep.h"
16
#include "qemu/units.h"
17
#include "qapi/error.h"
19
#include "hw/s390x/sclp.h"
20
#include "hw/s390x/event-facility.h"
21
#include "hw/s390x/s390-pci-bus.h"
22
#include "hw/s390x/ipl.h"
23
#include "hw/s390x/cpu-topology.h"
24
#include "hw/s390x/s390-virtio-ccw.h"
26
static SCLPDevice *get_sclp_device(void)
28
static SCLPDevice *sclp;
31
sclp = S390_CCW_MACHINE(qdev_get_machine())->sclp;
36
static inline bool sclp_command_code_valid(uint32_t code)
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:
52
static bool sccb_verify_boundary(uint64_t sccb_addr, uint16_t sccb_len,
55
uint64_t sccb_max_addr = sccb_addr + sccb_len - 1;
56
uint64_t sccb_boundary = (sccb_addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
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:
68
if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
73
if (sccb_max_addr < sccb_boundary) {
81
static void prepare_cpu_entries(MachineState *ms, CPUEntry *entry, int *count)
83
uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
86
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CPU, features);
87
for (i = 0, *count = 0; i < ms->possible_cpus->len; i++) {
88
if (!ms->possible_cpus->cpus[i].cpu) {
91
entry[*count].address = ms->possible_cpus->cpus[i].arch_id;
92
entry[*count].type = 0;
93
memcpy(entry[*count].features, features, sizeof(features));
98
#define SCCB_REQ_LEN(s, max_cpus) (sizeof(s) + max_cpus * sizeof(CPUEntry))
100
static inline bool ext_len_sccb_supported(SCCBHeader header)
102
return s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) &&
103
header.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE;
107
static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
109
ReadInfo *read_info = (ReadInfo *) sccb;
110
MachineState *machine = MACHINE(qdev_get_machine());
113
IplParameterBlock *ipib = s390_ipl_get_iplb();
114
int required_len = SCCB_REQ_LEN(ReadInfo, machine->possible_cpus->len);
115
int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ?
116
offsetof(ReadInfo, entries) :
117
SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET;
118
CPUEntry *entries_start = (void *)sccb + offset_cpu;
120
if (be16_to_cpu(sccb->h.length) < required_len) {
121
if (ext_len_sccb_supported(sccb->h)) {
122
sccb->h.length = cpu_to_be16(required_len);
124
sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
128
if (s390_has_topology()) {
129
read_info->stsi_parm = SCLP_READ_SCP_INFO_MNEST;
133
prepare_cpu_entries(machine, entries_start, &cpu_count);
134
read_info->entries_cpu = cpu_to_be16(cpu_count);
135
read_info->offset_cpu = cpu_to_be16(offset_cpu);
136
read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
138
read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
141
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR,
142
read_info->conf_char);
143
s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
144
read_info->conf_char_ext);
146
if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
147
s390_get_feat_block(S390_FEAT_TYPE_SCLP_FAC134,
151
read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
152
SCLP_HAS_IOA_RECONFIG);
154
read_info->mha_pow = s390_get_mha_pow();
155
read_info->hmfai = cpu_to_be32(s390_get_hmfai());
157
rnsize = 1 << (sclp->increment_size - 20);
159
read_info->rnsize = rnsize;
161
read_info->rnsize = 0;
162
read_info->rnsize2 = cpu_to_be32(rnsize);
166
rnmax = machine->ram_size >> sclp->increment_size;
167
if (rnmax < 0x10000) {
168
read_info->rnmax = cpu_to_be16(rnmax);
170
read_info->rnmax = cpu_to_be16(0);
171
read_info->rnmax2 = cpu_to_be64(rnmax);
174
if (ipib && ipib->flags & DIAG308_FLAGS_LP_VALID) {
175
memcpy(&read_info->loadparm, &ipib->loadparm,
176
sizeof(read_info->loadparm));
178
s390_ipl_set_loadparm(read_info->loadparm);
181
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
185
static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
187
MachineState *machine = MACHINE(qdev_get_machine());
188
ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
190
int required_len = SCCB_REQ_LEN(ReadCpuInfo, machine->possible_cpus->len);
192
if (be16_to_cpu(sccb->h.length) < required_len) {
193
if (ext_len_sccb_supported(sccb->h)) {
194
sccb->h.length = cpu_to_be16(required_len);
196
sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
200
prepare_cpu_entries(machine, cpu_info->entries, &cpu_count);
201
cpu_info->nr_configured = cpu_to_be16(cpu_count);
202
cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
203
cpu_info->nr_standby = cpu_to_be16(0);
206
cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
207
+ cpu_info->nr_configured*sizeof(CPUEntry));
210
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
213
static void sclp_configure_io_adapter(SCLPDevice *sclp, SCCB *sccb,
218
if (be16_to_cpu(sccb->h.length) < 16) {
219
rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
223
switch (((IoaCfgSccb *)sccb)->atype) {
224
case SCLP_RECONFIG_PCI_ATYPE:
225
if (s390_has_feat(S390_FEAT_ZPCI)) {
227
s390_pci_sclp_configure(sccb);
229
s390_pci_sclp_deconfigure(sccb);
235
rc = SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED;
239
sccb->h.response_code = cpu_to_be16(rc);
242
static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
244
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
245
SCLPEventFacility *ef = sclp->event_facility;
246
SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
248
switch (code & SCLP_CMD_CODE_MASK) {
249
case SCLP_CMDW_READ_SCP_INFO:
250
case SCLP_CMDW_READ_SCP_INFO_FORCED:
251
sclp_c->read_SCP_info(sclp, sccb);
253
case SCLP_CMDW_READ_CPU_INFO:
254
sclp_c->read_cpu_info(sclp, sccb);
256
case SCLP_CMDW_CONFIGURE_IOA:
257
sclp_configure_io_adapter(sclp, sccb, true);
259
case SCLP_CMDW_DECONFIGURE_IOA:
260
sclp_configure_io_adapter(sclp, sccb, false);
263
efc->command_handler(ef, sccb, code);
272
#define SCLP_PV_DUMMY_ADDR 0x4000
273
int sclp_service_call_protected(S390CPU *cpu, uint64_t sccb, uint32_t code)
275
CPUS390XState *env = &cpu->env;
276
SCLPDevice *sclp = get_sclp_device();
277
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
279
g_autofree SCCB *work_sccb = NULL;
281
s390_cpu_pv_mem_read(env_archcpu(env), 0, &header, sizeof(SCCBHeader));
283
work_sccb = g_malloc0(be16_to_cpu(header.length));
284
s390_cpu_pv_mem_read(env_archcpu(env), 0, work_sccb,
285
be16_to_cpu(header.length));
287
if (!sclp_command_code_valid(code)) {
288
work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
292
sclp_c->execute(sclp, work_sccb, code);
294
s390_cpu_pv_mem_write(env_archcpu(env), 0, work_sccb,
295
be16_to_cpu(work_sccb->h.length));
296
sclp_c->service_interrupt(sclp, SCLP_PV_DUMMY_ADDR);
300
int sclp_service_call(S390CPU *cpu, uint64_t sccb, uint32_t code)
302
CPUS390XState *env = &cpu->env;
303
SCLPDevice *sclp = get_sclp_device();
304
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
306
g_autofree SCCB *work_sccb = NULL;
309
if (env->psw.mask & PSW_MASK_PSTATE) {
310
return -PGM_PRIVILEGED;
312
if (cpu_physical_memory_is_io(sccb)) {
313
return -PGM_ADDRESSING;
315
if ((sccb & ~0x1fffUL) == 0 || (sccb & ~0x1fffUL) == env->psa
316
|| (sccb & ~0x7ffffff8UL) != 0) {
317
return -PGM_SPECIFICATION;
321
cpu_physical_memory_read(sccb, &header, sizeof(SCCBHeader));
324
if (be16_to_cpu(header.length) < sizeof(SCCBHeader)) {
325
return -PGM_SPECIFICATION;
333
work_sccb = g_malloc0(be16_to_cpu(header.length));
334
cpu_physical_memory_read(sccb, work_sccb, be16_to_cpu(header.length));
336
if (!sclp_command_code_valid(code)) {
337
work_sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
341
if (!sccb_verify_boundary(sccb, be16_to_cpu(work_sccb->h.length), code)) {
342
work_sccb->h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
346
sclp_c->execute(sclp, work_sccb, code);
348
cpu_physical_memory_write(sccb, work_sccb,
349
be16_to_cpu(work_sccb->h.length));
351
sclp_c->service_interrupt(sclp, sccb);
356
static void service_interrupt(SCLPDevice *sclp, uint32_t sccb)
358
SCLPEventFacility *ef = sclp->event_facility;
359
SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
361
uint32_t param = sccb & ~3;
364
param |= efc->event_pending(ef) ? 1 : 0;
370
s390_sclp_extint(param);
373
void sclp_service_interrupt(uint32_t sccb)
375
SCLPDevice *sclp = get_sclp_device();
376
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
378
sclp_c->service_interrupt(sclp, sccb);
382
static void sclp_realize(DeviceState *dev, Error **errp)
384
MachineState *machine = MACHINE(qdev_get_machine());
385
SCLPDevice *sclp = SCLP(dev);
394
if (!sysbus_realize(SYS_BUS_DEVICE(sclp->event_facility), errp)) {
398
ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
400
error_setg(errp, "host supports a maximum of %" PRIu64 " GB",
403
error_setg(errp, "setting the guest size failed");
407
static void sclp_memory_init(SCLPDevice *sclp)
409
MachineState *machine = MACHINE(qdev_get_machine());
410
MachineClass *machine_class = MACHINE_GET_CLASS(qdev_get_machine());
411
ram_addr_t initial_mem = machine->ram_size;
412
int increment_size = 20;
419
while (machine_class->fixup_ram_size != NULL &&
420
(initial_mem >> increment_size) > MAX_STORAGE_INCREMENTS) {
423
sclp->increment_size = increment_size;
426
static void sclp_init(Object *obj)
428
SCLPDevice *sclp = SCLP(obj);
431
new = object_new(TYPE_SCLP_EVENT_FACILITY);
432
object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new);
434
sclp->event_facility = EVENT_FACILITY(new);
436
sclp_memory_init(sclp);
439
static void sclp_class_init(ObjectClass *oc, void *data)
441
SCLPDeviceClass *sc = SCLP_CLASS(oc);
442
DeviceClass *dc = DEVICE_CLASS(oc);
444
dc->desc = "SCLP (Service-Call Logical Processor)";
445
dc->realize = sclp_realize;
446
dc->hotpluggable = false;
447
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
452
dc->user_creatable = false;
454
sc->read_SCP_info = read_SCP_info;
455
sc->read_cpu_info = sclp_read_cpu_info;
456
sc->execute = sclp_execute;
457
sc->service_interrupt = service_interrupt;
460
static const TypeInfo sclp_info = {
462
.parent = TYPE_DEVICE,
463
.instance_init = sclp_init,
464
.instance_size = sizeof(SCLPDevice),
465
.class_init = sclp_class_init,
466
.class_size = sizeof(SCLPDeviceClass),
469
static void register_types(void)
471
type_register_static(&sclp_info);
473
type_init(register_types);