xref: /openbmc/qemu/hw/s390x/sclp.c (revision e6e03dcf)
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 
15 #include "qemu/osdep.h"
16 #include "qemu/units.h"
17 #include "qapi/error.h"
18 #include "cpu.h"
19 #include "sysemu/sysemu.h"
20 #include "hw/boards.h"
21 #include "hw/s390x/sclp.h"
22 #include "hw/s390x/event-facility.h"
23 #include "hw/s390x/s390-pci-bus.h"
24 #include "hw/s390x/ipl.h"
25 
26 static inline SCLPDevice *get_sclp_device(void)
27 {
28     static SCLPDevice *sclp;
29 
30     if (!sclp) {
31         sclp = SCLP(object_resolve_path_type("", TYPE_SCLP, NULL));
32     }
33     return sclp;
34 }
35 
36 static void prepare_cpu_entries(SCLPDevice *sclp, CPUEntry *entry, int *count)
37 {
38     MachineState *ms = MACHINE(qdev_get_machine());
39     uint8_t features[SCCB_CPU_FEATURE_LEN] = { 0 };
40     int i;
41 
42     s390_get_feat_block(S390_FEAT_TYPE_SCLP_CPU, features);
43     for (i = 0, *count = 0; i < ms->possible_cpus->len; i++) {
44         if (!ms->possible_cpus->cpus[i].cpu) {
45             continue;
46         }
47         entry[*count].address = ms->possible_cpus->cpus[i].arch_id;
48         entry[*count].type = 0;
49         memcpy(entry[*count].features, features, sizeof(features));
50         (*count)++;
51     }
52 }
53 
54 /* Provide information about the configuration, CPUs and storage */
55 static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
56 {
57     ReadInfo *read_info = (ReadInfo *) sccb;
58     MachineState *machine = MACHINE(qdev_get_machine());
59     int cpu_count;
60     int rnsize, rnmax;
61     IplParameterBlock *ipib = s390_ipl_get_iplb();
62 
63     /* CPU information */
64     prepare_cpu_entries(sclp, read_info->entries, &cpu_count);
65     read_info->entries_cpu = cpu_to_be16(cpu_count);
66     read_info->offset_cpu = cpu_to_be16(offsetof(ReadInfo, entries));
67     read_info->highest_cpu = cpu_to_be16(machine->smp.max_cpus - 1);
68 
69     read_info->ibc_val = cpu_to_be32(s390_get_ibc_val());
70 
71     if (be16_to_cpu(sccb->h.length) <
72             (sizeof(ReadInfo) + cpu_count * sizeof(CPUEntry))) {
73         sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
74         return;
75     }
76 
77     /* Configuration Characteristic (Extension) */
78     s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR,
79                          read_info->conf_char);
80     s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
81                          read_info->conf_char_ext);
82 
83     read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
84                                         SCLP_HAS_IOA_RECONFIG);
85 
86     read_info->mha_pow = s390_get_mha_pow();
87     read_info->hmfai = cpu_to_be32(s390_get_hmfai());
88 
89     rnsize = 1 << (sclp->increment_size - 20);
90     if (rnsize <= 128) {
91         read_info->rnsize = rnsize;
92     } else {
93         read_info->rnsize = 0;
94         read_info->rnsize2 = cpu_to_be32(rnsize);
95     }
96 
97     /* we don't support standby memory, maxram_size is never exposed */
98     rnmax = machine->ram_size >> sclp->increment_size;
99     if (rnmax < 0x10000) {
100         read_info->rnmax = cpu_to_be16(rnmax);
101     } else {
102         read_info->rnmax = cpu_to_be16(0);
103         read_info->rnmax2 = cpu_to_be64(rnmax);
104     }
105 
106     if (ipib && ipib->flags & DIAG308_FLAGS_LP_VALID) {
107         memcpy(&read_info->loadparm, &ipib->loadparm,
108                sizeof(read_info->loadparm));
109     } else {
110         s390_ipl_set_loadparm(read_info->loadparm);
111     }
112 
113     sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
114 }
115 
116 /* Provide information about the CPU */
117 static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
118 {
119     ReadCpuInfo *cpu_info = (ReadCpuInfo *) sccb;
120     int cpu_count;
121 
122     prepare_cpu_entries(sclp, cpu_info->entries, &cpu_count);
123     cpu_info->nr_configured = cpu_to_be16(cpu_count);
124     cpu_info->offset_configured = cpu_to_be16(offsetof(ReadCpuInfo, entries));
125     cpu_info->nr_standby = cpu_to_be16(0);
126 
127     if (be16_to_cpu(sccb->h.length) <
128             (sizeof(ReadCpuInfo) + cpu_count * sizeof(CPUEntry))) {
129         sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
130         return;
131     }
132 
133     /* The standby offset is 16-byte for each CPU */
134     cpu_info->offset_standby = cpu_to_be16(cpu_info->offset_configured
135         + cpu_info->nr_configured*sizeof(CPUEntry));
136 
137 
138     sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
139 }
140 
141 static void sclp_configure_io_adapter(SCLPDevice *sclp, SCCB *sccb,
142                                       bool configure)
143 {
144     int rc;
145 
146     if (be16_to_cpu(sccb->h.length) < 16) {
147         rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
148         goto out_err;
149     }
150 
151     switch (((IoaCfgSccb *)sccb)->atype) {
152     case SCLP_RECONFIG_PCI_ATYPE:
153         if (s390_has_feat(S390_FEAT_ZPCI)) {
154             if (configure) {
155                 s390_pci_sclp_configure(sccb);
156             } else {
157                 s390_pci_sclp_deconfigure(sccb);
158             }
159             return;
160         }
161         /* fallthrough */
162     default:
163         rc = SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED;
164     }
165 
166  out_err:
167     sccb->h.response_code = cpu_to_be16(rc);
168 }
169 
170 static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
171 {
172     SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
173     SCLPEventFacility *ef = sclp->event_facility;
174     SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
175 
176     switch (code & SCLP_CMD_CODE_MASK) {
177     case SCLP_CMDW_READ_SCP_INFO:
178     case SCLP_CMDW_READ_SCP_INFO_FORCED:
179         sclp_c->read_SCP_info(sclp, sccb);
180         break;
181     case SCLP_CMDW_READ_CPU_INFO:
182         sclp_c->read_cpu_info(sclp, sccb);
183         break;
184     case SCLP_CMDW_CONFIGURE_IOA:
185         sclp_configure_io_adapter(sclp, sccb, true);
186         break;
187     case SCLP_CMDW_DECONFIGURE_IOA:
188         sclp_configure_io_adapter(sclp, sccb, false);
189         break;
190     default:
191         efc->command_handler(ef, sccb, code);
192         break;
193     }
194 }
195 
196 int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code)
197 {
198     SCLPDevice *sclp = get_sclp_device();
199     SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
200     int r = 0;
201     SCCB work_sccb;
202 
203     hwaddr sccb_len = sizeof(SCCB);
204 
205     /* first some basic checks on program checks */
206     if (env->psw.mask & PSW_MASK_PSTATE) {
207         r = -PGM_PRIVILEGED;
208         goto out;
209     }
210     if (cpu_physical_memory_is_io(sccb)) {
211         r = -PGM_ADDRESSING;
212         goto out;
213     }
214     if ((sccb & ~0x1fffUL) == 0 || (sccb & ~0x1fffUL) == env->psa
215         || (sccb & ~0x7ffffff8UL) != 0) {
216         r = -PGM_SPECIFICATION;
217         goto out;
218     }
219 
220     /*
221      * we want to work on a private copy of the sccb, to prevent guests
222      * from playing dirty tricks by modifying the memory content after
223      * the host has checked the values
224      */
225     cpu_physical_memory_read(sccb, &work_sccb, sccb_len);
226 
227     /* Valid sccb sizes */
228     if (be16_to_cpu(work_sccb.h.length) < sizeof(SCCBHeader)) {
229         r = -PGM_SPECIFICATION;
230         goto out;
231     }
232 
233     switch (code & SCLP_CMD_CODE_MASK) {
234     case SCLP_CMDW_READ_SCP_INFO:
235     case SCLP_CMDW_READ_SCP_INFO_FORCED:
236     case SCLP_CMDW_READ_CPU_INFO:
237     case SCLP_CMDW_CONFIGURE_IOA:
238     case SCLP_CMDW_DECONFIGURE_IOA:
239     case SCLP_CMD_READ_EVENT_DATA:
240     case SCLP_CMD_WRITE_EVENT_DATA:
241     case SCLP_CMD_WRITE_EVENT_MASK:
242         break;
243     default:
244         work_sccb.h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
245         goto out_write;
246     }
247 
248     if ((sccb + be16_to_cpu(work_sccb.h.length)) > ((sccb & PAGE_MASK) + PAGE_SIZE)) {
249         work_sccb.h.response_code = cpu_to_be16(SCLP_RC_SCCB_BOUNDARY_VIOLATION);
250         goto out_write;
251     }
252 
253     sclp_c->execute(sclp, &work_sccb, code);
254 out_write:
255     cpu_physical_memory_write(sccb, &work_sccb,
256                               be16_to_cpu(work_sccb.h.length));
257 
258     sclp_c->service_interrupt(sclp, sccb);
259 
260 out:
261     return r;
262 }
263 
264 static void service_interrupt(SCLPDevice *sclp, uint32_t sccb)
265 {
266     SCLPEventFacility *ef = sclp->event_facility;
267     SCLPEventFacilityClass *efc = EVENT_FACILITY_GET_CLASS(ef);
268 
269     uint32_t param = sccb & ~3;
270 
271     /* Indicate whether an event is still pending */
272     param |= efc->event_pending(ef) ? 1 : 0;
273 
274     if (!param) {
275         /* No need to send an interrupt, there's nothing to be notified about */
276         return;
277     }
278     s390_sclp_extint(param);
279 }
280 
281 void sclp_service_interrupt(uint32_t sccb)
282 {
283     SCLPDevice *sclp = get_sclp_device();
284     SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
285 
286     sclp_c->service_interrupt(sclp, sccb);
287 }
288 
289 /* qemu object creation and initialization functions */
290 
291 void s390_sclp_init(void)
292 {
293     Object *new = object_new(TYPE_SCLP);
294 
295     object_property_add_child(qdev_get_machine(), TYPE_SCLP, new,
296                               NULL);
297     object_unref(OBJECT(new));
298     qdev_init_nofail(DEVICE(new));
299 }
300 
301 static void sclp_realize(DeviceState *dev, Error **errp)
302 {
303     MachineState *machine = MACHINE(qdev_get_machine());
304     SCLPDevice *sclp = SCLP(dev);
305     Error *err = NULL;
306     uint64_t hw_limit;
307     int ret;
308 
309     object_property_set_bool(OBJECT(sclp->event_facility), true, "realized",
310                              &err);
311     if (err) {
312         goto out;
313     }
314     /*
315      * qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long
316      * as we can't find a fitting bus via the qom tree, we have to add the
317      * event facility to the sysbus, so e.g. a sclp console can be created.
318      */
319     qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default());
320 
321     ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
322     if (ret == -E2BIG) {
323         error_setg(&err, "host supports a maximum of %" PRIu64 " GB",
324                    hw_limit / GiB);
325     } else if (ret) {
326         error_setg(&err, "setting the guest size failed");
327     }
328 
329 out:
330     error_propagate(errp, err);
331 }
332 
333 static void sclp_memory_init(SCLPDevice *sclp)
334 {
335     MachineState *machine = MACHINE(qdev_get_machine());
336     ram_addr_t initial_mem = machine->ram_size;
337     int increment_size = 20;
338 
339     /* The storage increment size is a multiple of 1M and is a power of 2.
340      * The number of storage increments must be MAX_STORAGE_INCREMENTS or fewer.
341      * The variable 'increment_size' is an exponent of 2 that can be
342      * used to calculate the size (in bytes) of an increment. */
343     while ((initial_mem >> increment_size) > MAX_STORAGE_INCREMENTS) {
344         increment_size++;
345     }
346     sclp->increment_size = increment_size;
347 
348     /* The core memory area needs to be aligned with the increment size.
349      * In effect, this can cause the user-specified memory size to be rounded
350      * down to align with the nearest increment boundary. */
351     initial_mem = initial_mem >> increment_size << increment_size;
352 
353     machine->ram_size = initial_mem;
354     machine->maxram_size = initial_mem;
355     /* let's propagate the changed ram size into the global variable. */
356     ram_size = initial_mem;
357 }
358 
359 static void sclp_init(Object *obj)
360 {
361     SCLPDevice *sclp = SCLP(obj);
362     Object *new;
363 
364     new = object_new(TYPE_SCLP_EVENT_FACILITY);
365     object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new, NULL);
366     object_unref(new);
367     sclp->event_facility = EVENT_FACILITY(new);
368 
369     sclp_memory_init(sclp);
370 }
371 
372 static void sclp_class_init(ObjectClass *oc, void *data)
373 {
374     SCLPDeviceClass *sc = SCLP_CLASS(oc);
375     DeviceClass *dc = DEVICE_CLASS(oc);
376 
377     dc->desc = "SCLP (Service-Call Logical Processor)";
378     dc->realize = sclp_realize;
379     dc->hotpluggable = false;
380     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
381     /*
382      * Reason: Creates TYPE_SCLP_EVENT_FACILITY in sclp_init
383      * which is a non-pluggable sysbus device
384      */
385     dc->user_creatable = false;
386 
387     sc->read_SCP_info = read_SCP_info;
388     sc->read_cpu_info = sclp_read_cpu_info;
389     sc->execute = sclp_execute;
390     sc->service_interrupt = service_interrupt;
391 }
392 
393 static TypeInfo sclp_info = {
394     .name = TYPE_SCLP,
395     .parent = TYPE_DEVICE,
396     .instance_init = sclp_init,
397     .instance_size = sizeof(SCLPDevice),
398     .class_init = sclp_class_init,
399     .class_size = sizeof(SCLPDeviceClass),
400 };
401 
402 static void register_types(void)
403 {
404     type_register_static(&sclp_info);
405 }
406 type_init(register_types);
407