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