xref: /openbmc/qemu/target/s390x/cpu.c (revision 0b1183e3)
1 /*
2  * QEMU S/390 CPU
3  *
4  * Copyright (c) 2009 Ulrich Hecht
5  * Copyright (c) 2011 Alexander Graf
6  * Copyright (c) 2012 SUSE LINUX Products GmbH
7  * Copyright (c) 2012 IBM Corp.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, see
21  * <http://www.gnu.org/licenses/lgpl-2.1.html>
22  * Contributions after 2012-12-11 are licensed under the terms of the
23  * GNU GPL, version 2 or (at your option) any later version.
24  */
25 
26 #include "qemu/osdep.h"
27 #include "qapi/error.h"
28 #include "cpu.h"
29 #include "qemu-common.h"
30 #include "qemu/cutils.h"
31 #include "qemu/timer.h"
32 #include "qemu/error-report.h"
33 #include "trace.h"
34 #include "qapi/visitor.h"
35 #include "exec/exec-all.h"
36 #ifndef CONFIG_USER_ONLY
37 #include "hw/hw.h"
38 #include "sysemu/arch_init.h"
39 #include "sysemu/sysemu.h"
40 #include "hw/s390x/sclp.h"
41 #endif
42 
43 #define CR0_RESET       0xE0UL
44 #define CR14_RESET      0xC2000000UL;
45 
46 static void s390_cpu_set_pc(CPUState *cs, vaddr value)
47 {
48     S390CPU *cpu = S390_CPU(cs);
49 
50     cpu->env.psw.addr = value;
51 }
52 
53 static bool s390_cpu_has_work(CPUState *cs)
54 {
55     S390CPU *cpu = S390_CPU(cs);
56     CPUS390XState *env = &cpu->env;
57 
58     return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
59            (env->psw.mask & PSW_MASK_EXT);
60 }
61 
62 #if !defined(CONFIG_USER_ONLY)
63 /* S390CPUClass::load_normal() */
64 static void s390_cpu_load_normal(CPUState *s)
65 {
66     S390CPU *cpu = S390_CPU(s);
67     cpu->env.psw.addr = ldl_phys(s->as, 4) & PSW_MASK_ESA_ADDR;
68     cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64;
69     s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
70 }
71 #endif
72 
73 /* S390CPUClass::cpu_reset() */
74 static void s390_cpu_reset(CPUState *s)
75 {
76     S390CPU *cpu = S390_CPU(s);
77     S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
78     CPUS390XState *env = &cpu->env;
79 
80     env->pfault_token = -1UL;
81     scc->parent_reset(s);
82     cpu->env.sigp_order = 0;
83     s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
84 }
85 
86 /* S390CPUClass::initial_reset() */
87 static void s390_cpu_initial_reset(CPUState *s)
88 {
89     S390CPU *cpu = S390_CPU(s);
90     CPUS390XState *env = &cpu->env;
91     int i;
92 
93     s390_cpu_reset(s);
94     /* initial reset does not clear everything! */
95     memset(&env->start_initial_reset_fields, 0,
96         offsetof(CPUS390XState, end_reset_fields) -
97         offsetof(CPUS390XState, start_initial_reset_fields));
98 
99     /* architectured initial values for CR 0 and 14 */
100     env->cregs[0] = CR0_RESET;
101     env->cregs[14] = CR14_RESET;
102 
103     /* architectured initial value for Breaking-Event-Address register */
104     env->gbea = 1;
105 
106     env->pfault_token = -1UL;
107     env->ext_index = -1;
108     for (i = 0; i < ARRAY_SIZE(env->io_index); i++) {
109         env->io_index[i] = -1;
110     }
111 
112     /* tininess for underflow is detected before rounding */
113     set_float_detect_tininess(float_tininess_before_rounding,
114                               &env->fpu_status);
115 
116     /* Reset state inside the kernel that we cannot access yet from QEMU. */
117     if (kvm_enabled()) {
118         kvm_s390_reset_vcpu(cpu);
119     }
120 }
121 
122 /* CPUClass:reset() */
123 static void s390_cpu_full_reset(CPUState *s)
124 {
125     S390CPU *cpu = S390_CPU(s);
126     S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
127     CPUS390XState *env = &cpu->env;
128     int i;
129 
130     scc->parent_reset(s);
131     cpu->env.sigp_order = 0;
132     s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
133 
134     memset(env, 0, offsetof(CPUS390XState, end_reset_fields));
135 
136     /* architectured initial values for CR 0 and 14 */
137     env->cregs[0] = CR0_RESET;
138     env->cregs[14] = CR14_RESET;
139 
140     /* architectured initial value for Breaking-Event-Address register */
141     env->gbea = 1;
142 
143     env->pfault_token = -1UL;
144     env->ext_index = -1;
145     for (i = 0; i < ARRAY_SIZE(env->io_index); i++) {
146         env->io_index[i] = -1;
147     }
148 
149     /* tininess for underflow is detected before rounding */
150     set_float_detect_tininess(float_tininess_before_rounding,
151                               &env->fpu_status);
152 
153     /* Reset state inside the kernel that we cannot access yet from QEMU. */
154     if (kvm_enabled()) {
155         kvm_s390_reset_vcpu(cpu);
156     }
157 }
158 
159 #if !defined(CONFIG_USER_ONLY)
160 static void s390_cpu_machine_reset_cb(void *opaque)
161 {
162     S390CPU *cpu = opaque;
163 
164     run_on_cpu(CPU(cpu), s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
165 }
166 #endif
167 
168 static void s390_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
169 {
170     info->mach = bfd_mach_s390_64;
171     info->print_insn = print_insn_s390;
172 }
173 
174 static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
175 {
176     CPUState *cs = CPU(dev);
177     S390CPUClass *scc = S390_CPU_GET_CLASS(dev);
178     S390CPU *cpu = S390_CPU(dev);
179     CPUS390XState *env = &cpu->env;
180     Error *err = NULL;
181 
182     /* the model has to be realized before qemu_init_vcpu() due to kvm */
183     s390_realize_cpu_model(cs, &err);
184     if (err) {
185         goto out;
186     }
187 
188 #if !defined(CONFIG_USER_ONLY)
189     if (cpu->id >= max_cpus) {
190         error_setg(&err, "Unable to add CPU: %" PRIi64
191                    ", max allowed: %d", cpu->id, max_cpus - 1);
192         goto out;
193     }
194 #endif
195     if (cpu_exists(cpu->id)) {
196         error_setg(&err, "Unable to add CPU: %" PRIi64
197                    ", it already exists", cpu->id);
198         goto out;
199     }
200     if (cpu->id != scc->next_cpu_id) {
201         error_setg(&err, "Unable to add CPU: %" PRIi64
202                    ", The next available id is %" PRIi64, cpu->id,
203                    scc->next_cpu_id);
204         goto out;
205     }
206 
207     cpu_exec_realizefn(cs, &err);
208     if (err != NULL) {
209         goto out;
210     }
211     scc->next_cpu_id++;
212 
213 #if !defined(CONFIG_USER_ONLY)
214     qemu_register_reset(s390_cpu_machine_reset_cb, cpu);
215 #endif
216     env->cpu_num = cpu->id;
217     s390_cpu_gdb_init(cs);
218     qemu_init_vcpu(cs);
219 #if !defined(CONFIG_USER_ONLY)
220     run_on_cpu(cs, s390_do_cpu_full_reset, RUN_ON_CPU_NULL);
221 #else
222     cpu_reset(cs);
223 #endif
224 
225     scc->parent_realize(dev, &err);
226 
227 #if !defined(CONFIG_USER_ONLY)
228     if (dev->hotplugged) {
229         raise_irq_cpu_hotplug();
230     }
231 #endif
232 
233 out:
234     error_propagate(errp, err);
235 }
236 
237 static void s390x_cpu_get_id(Object *obj, Visitor *v, const char *name,
238                              void *opaque, Error **errp)
239 {
240     S390CPU *cpu = S390_CPU(obj);
241     int64_t value = cpu->id;
242 
243     visit_type_int(v, name, &value, errp);
244 }
245 
246 static void s390x_cpu_set_id(Object *obj, Visitor *v, const char *name,
247                              void *opaque, Error **errp)
248 {
249     S390CPU *cpu = S390_CPU(obj);
250     DeviceState *dev = DEVICE(obj);
251     const int64_t min = 0;
252     const int64_t max = UINT32_MAX;
253     Error *err = NULL;
254     int64_t value;
255 
256     if (dev->realized) {
257         error_setg(errp, "Attempt to set property '%s' on '%s' after "
258                    "it was realized", name, object_get_typename(obj));
259         return;
260     }
261 
262     visit_type_int(v, name, &value, &err);
263     if (err) {
264         error_propagate(errp, err);
265         return;
266     }
267     if (value < min || value > max) {
268         error_setg(errp, "Property %s.%s doesn't take value %" PRId64
269                    " (minimum: %" PRId64 ", maximum: %" PRId64 ")" ,
270                    object_get_typename(obj), name, value, min, max);
271         return;
272     }
273     cpu->id = value;
274 }
275 
276 static void s390_cpu_initfn(Object *obj)
277 {
278     CPUState *cs = CPU(obj);
279     S390CPU *cpu = S390_CPU(obj);
280     CPUS390XState *env = &cpu->env;
281     static bool inited;
282 #if !defined(CONFIG_USER_ONLY)
283     struct tm tm;
284 #endif
285 
286     cs->env_ptr = env;
287     cs->halted = 1;
288     cs->exception_index = EXCP_HLT;
289     object_property_add(OBJECT(cpu), "id", "int64_t", s390x_cpu_get_id,
290                         s390x_cpu_set_id, NULL, NULL, NULL);
291     s390_cpu_model_register_props(obj);
292 #if !defined(CONFIG_USER_ONLY)
293     qemu_get_timedate(&tm, 0);
294     env->tod_offset = TOD_UNIX_EPOCH +
295                       (time2tod(mktimegm(&tm)) * 1000000000ULL);
296     env->tod_basetime = 0;
297     env->tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu);
298     env->cpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu);
299     s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
300 #endif
301 
302     if (tcg_enabled() && !inited) {
303         inited = true;
304         s390x_translate_init();
305     }
306 }
307 
308 static void s390_cpu_finalize(Object *obj)
309 {
310 #if !defined(CONFIG_USER_ONLY)
311     S390CPU *cpu = S390_CPU(obj);
312 
313     qemu_unregister_reset(s390_cpu_machine_reset_cb, cpu);
314     g_free(cpu->irqstate);
315 #endif
316 }
317 
318 #if !defined(CONFIG_USER_ONLY)
319 static bool disabled_wait(CPUState *cpu)
320 {
321     return cpu->halted && !(S390_CPU(cpu)->env.psw.mask &
322                             (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK));
323 }
324 
325 static unsigned s390_count_running_cpus(void)
326 {
327     CPUState *cpu;
328     int nr_running = 0;
329 
330     CPU_FOREACH(cpu) {
331         uint8_t state = S390_CPU(cpu)->env.cpu_state;
332         if (state == CPU_STATE_OPERATING ||
333             state == CPU_STATE_LOAD) {
334             if (!disabled_wait(cpu)) {
335                 nr_running++;
336             }
337         }
338     }
339 
340     return nr_running;
341 }
342 
343 unsigned int s390_cpu_halt(S390CPU *cpu)
344 {
345     CPUState *cs = CPU(cpu);
346     trace_cpu_halt(cs->cpu_index);
347 
348     if (!cs->halted) {
349         cs->halted = 1;
350         cs->exception_index = EXCP_HLT;
351     }
352 
353     return s390_count_running_cpus();
354 }
355 
356 void s390_cpu_unhalt(S390CPU *cpu)
357 {
358     CPUState *cs = CPU(cpu);
359     trace_cpu_unhalt(cs->cpu_index);
360 
361     if (cs->halted) {
362         cs->halted = 0;
363         cs->exception_index = -1;
364     }
365 }
366 
367 unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
368  {
369     trace_cpu_set_state(CPU(cpu)->cpu_index, cpu_state);
370 
371     switch (cpu_state) {
372     case CPU_STATE_STOPPED:
373     case CPU_STATE_CHECK_STOP:
374         /* halt the cpu for common infrastructure */
375         s390_cpu_halt(cpu);
376         break;
377     case CPU_STATE_OPERATING:
378     case CPU_STATE_LOAD:
379         /* unhalt the cpu for common infrastructure */
380         s390_cpu_unhalt(cpu);
381         break;
382     default:
383         error_report("Requested CPU state is not a valid S390 CPU state: %u",
384                      cpu_state);
385         exit(1);
386     }
387     if (kvm_enabled() && cpu->env.cpu_state != cpu_state) {
388         kvm_s390_set_cpu_state(cpu, cpu_state);
389     }
390     cpu->env.cpu_state = cpu_state;
391 
392     return s390_count_running_cpus();
393 }
394 #endif
395 
396 static gchar *s390_gdb_arch_name(CPUState *cs)
397 {
398     return g_strdup("s390:64-bit");
399 }
400 
401 static void s390_cpu_class_init(ObjectClass *oc, void *data)
402 {
403     S390CPUClass *scc = S390_CPU_CLASS(oc);
404     CPUClass *cc = CPU_CLASS(scc);
405     DeviceClass *dc = DEVICE_CLASS(oc);
406 
407     scc->next_cpu_id = 0;
408     scc->parent_realize = dc->realize;
409     dc->realize = s390_cpu_realizefn;
410 
411     scc->parent_reset = cc->reset;
412 #if !defined(CONFIG_USER_ONLY)
413     scc->load_normal = s390_cpu_load_normal;
414 #endif
415     scc->cpu_reset = s390_cpu_reset;
416     scc->initial_cpu_reset = s390_cpu_initial_reset;
417     cc->reset = s390_cpu_full_reset;
418     cc->class_by_name = s390_cpu_class_by_name,
419     cc->has_work = s390_cpu_has_work;
420     cc->do_interrupt = s390_cpu_do_interrupt;
421     cc->dump_state = s390_cpu_dump_state;
422     cc->set_pc = s390_cpu_set_pc;
423     cc->gdb_read_register = s390_cpu_gdb_read_register;
424     cc->gdb_write_register = s390_cpu_gdb_write_register;
425 #ifdef CONFIG_USER_ONLY
426     cc->handle_mmu_fault = s390_cpu_handle_mmu_fault;
427 #else
428     cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
429     cc->vmsd = &vmstate_s390_cpu;
430     cc->write_elf64_note = s390_cpu_write_elf64_note;
431     cc->cpu_exec_interrupt = s390_cpu_exec_interrupt;
432     cc->debug_excp_handler = s390x_cpu_debug_excp_handler;
433     cc->do_unaligned_access = s390x_cpu_do_unaligned_access;
434 #endif
435     cc->disas_set_info = s390_cpu_disas_set_info;
436 
437     cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
438     cc->gdb_core_xml_file = "s390x-core64.xml";
439     cc->gdb_arch_name = s390_gdb_arch_name;
440 
441     s390_cpu_model_class_register_props(oc);
442 }
443 
444 static const TypeInfo s390_cpu_type_info = {
445     .name = TYPE_S390_CPU,
446     .parent = TYPE_CPU,
447     .instance_size = sizeof(S390CPU),
448     .instance_init = s390_cpu_initfn,
449     .instance_finalize = s390_cpu_finalize,
450     .abstract = true,
451     .class_size = sizeof(S390CPUClass),
452     .class_init = s390_cpu_class_init,
453 };
454 
455 static void s390_cpu_register_types(void)
456 {
457     type_register_static(&s390_cpu_type_info);
458 }
459 
460 type_init(s390_cpu_register_types)
461