blob: d765e7b9849bd1fad49f74d111968023dae57c3c [file] [log] [blame]
Andreas Färber29e4bcb2012-04-02 11:39:23 +02001/*
2 * QEMU S/390 CPU
3 *
Andreas Färber1ac1a742012-04-02 13:31:59 +02004 * Copyright (c) 2009 Ulrich Hecht
5 * Copyright (c) 2011 Alexander Graf
Andreas Färber29e4bcb2012-04-02 11:39:23 +02006 * Copyright (c) 2012 SUSE LINUX Products GmbH
Jens Freimann70bada02013-01-07 05:27:14 +00007 * Copyright (c) 2012 IBM Corp.
Andreas Färber29e4bcb2012-04-02 11:39:23 +02008 *
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>
Jens Freimann70bada02013-01-07 05:27:14 +000022 * Contributions after 2012-12-11 are licensed under the terms of the
23 * GNU GPL, version 2 or (at your option) any later version.
Andreas Färber29e4bcb2012-04-02 11:39:23 +020024 */
25
Andreas Färber564b8632012-05-03 04:13:04 +020026#include "cpu.h"
Andreas Färber29e4bcb2012-04-02 11:39:23 +020027#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010028#include "qemu/timer.h"
Jens Freimann70bada02013-01-07 05:27:14 +000029#include "hw/hw.h"
Andreas Färberc7396bb2013-01-20 19:41:06 +010030#ifndef CONFIG_USER_ONLY
Viktor Mihajlovski904e5fd2012-12-18 07:50:59 +000031#include "sysemu/arch_init.h"
32#endif
Andreas Färber29e4bcb2012-04-02 11:39:23 +020033
Jens Freimann70bada02013-01-07 05:27:14 +000034#define CR0_RESET 0xE0UL
35#define CR14_RESET 0xC2000000UL;
36
Viktor Mihajlovski904e5fd2012-12-18 07:50:59 +000037/* generate CPU information for cpu -? */
38void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf)
39{
40#ifdef CONFIG_KVM
41 (*cpu_fprintf)(f, "s390 %16s\n", "host");
42#endif
43}
44
45#ifndef CONFIG_USER_ONLY
46CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
47{
48 CpuDefinitionInfoList *entry;
49 CpuDefinitionInfo *info;
50
51 info = g_malloc0(sizeof(*info));
52 info->name = g_strdup("host");
53
54 entry = g_malloc0(sizeof(*entry));
55 entry->value = info;
56
57 return entry;
58}
59#endif
Andreas Färber29e4bcb2012-04-02 11:39:23 +020060
Andreas Färber1ac1a742012-04-02 13:31:59 +020061/* CPUClass::reset() */
Andreas Färber29e4bcb2012-04-02 11:39:23 +020062static void s390_cpu_reset(CPUState *s)
63{
64 S390CPU *cpu = S390_CPU(s);
65 S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
66 CPUS390XState *env = &cpu->env;
67
Andreas Färber1ac1a742012-04-02 13:31:59 +020068 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
Andreas Färber55e5c282012-12-17 06:18:02 +010069 qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
Andreas Färber1ac1a742012-04-02 13:31:59 +020070 log_cpu_state(env, 0);
71 }
72
Andreas Färber49e15872013-01-30 12:48:25 +000073 s390_del_running_cpu(cpu);
Jens Freimann70bada02013-01-07 05:27:14 +000074
Andreas Färber29e4bcb2012-04-02 11:39:23 +020075 scc->parent_reset(s);
76
Andreas Färber1ac1a742012-04-02 13:31:59 +020077 memset(env, 0, offsetof(CPUS390XState, breakpoints));
Jens Freimann70bada02013-01-07 05:27:14 +000078
79 /* architectured initial values for CR 0 and 14 */
80 env->cregs[0] = CR0_RESET;
81 env->cregs[14] = CR14_RESET;
82 /* set halted to 1 to make sure we can add the cpu in
83 * s390_ipl_cpu code, where env->halted is set back to 0
84 * after incrementing the cpu counter */
85#if !defined(CONFIG_USER_ONLY)
86 env->halted = 1;
87#endif
Andreas Färber1ac1a742012-04-02 13:31:59 +020088 tlb_flush(env, 1);
Andreas Färber29e4bcb2012-04-02 11:39:23 +020089}
90
Jens Freimann70bada02013-01-07 05:27:14 +000091#if !defined(CONFIG_USER_ONLY)
92static void s390_cpu_machine_reset_cb(void *opaque)
93{
94 S390CPU *cpu = opaque;
95
96 cpu_reset(CPU(cpu));
97}
98#endif
99
Andreas Färber8f22e0d2012-04-02 13:56:29 +0200100static void s390_cpu_initfn(Object *obj)
101{
102 S390CPU *cpu = S390_CPU(obj);
103 CPUS390XState *env = &cpu->env;
104 static int cpu_num = 0;
105#if !defined(CONFIG_USER_ONLY)
106 struct tm tm;
107#endif
108
109 cpu_exec_init(env);
110#if !defined(CONFIG_USER_ONLY)
Jens Freimann70bada02013-01-07 05:27:14 +0000111 qemu_register_reset(s390_cpu_machine_reset_cb, cpu);
Andreas Färber8f22e0d2012-04-02 13:56:29 +0200112 qemu_get_timedate(&tm, 0);
113 env->tod_offset = TOD_UNIX_EPOCH +
114 (time2tod(mktimegm(&tm)) * 1000000000ULL);
115 env->tod_basetime = 0;
Andreas Färberb8ba6792012-04-02 14:00:43 +0200116 env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, cpu);
117 env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, cpu);
Jens Freimann70bada02013-01-07 05:27:14 +0000118 /* set env->halted state to 1 to avoid decrementing the running
119 * cpu counter in s390_cpu_reset to a negative number at
120 * initial ipl */
121 env->halted = 1;
Andreas Färber8f22e0d2012-04-02 13:56:29 +0200122#endif
123 env->cpu_num = cpu_num++;
124 env->ext_index = -1;
125
126 cpu_reset(CPU(cpu));
127}
128
Andreas Färberd5627ce2013-01-07 06:14:16 +0000129static void s390_cpu_finalize(Object *obj)
130{
131#if !defined(CONFIG_USER_ONLY)
132 S390CPU *cpu = S390_CPU(obj);
133
134 qemu_unregister_reset(s390_cpu_machine_reset_cb, cpu);
135#endif
136}
137
Andreas Färberc7396bb2013-01-20 19:41:06 +0100138static const VMStateDescription vmstate_s390_cpu = {
139 .name = "cpu",
140 .unmigratable = 1,
141};
142
Andreas Färber29e4bcb2012-04-02 11:39:23 +0200143static void s390_cpu_class_init(ObjectClass *oc, void *data)
144{
145 S390CPUClass *scc = S390_CPU_CLASS(oc);
146 CPUClass *cc = CPU_CLASS(scc);
Andreas Färberc7396bb2013-01-20 19:41:06 +0100147 DeviceClass *dc = DEVICE_CLASS(oc);
Andreas Färber29e4bcb2012-04-02 11:39:23 +0200148
149 scc->parent_reset = cc->reset;
150 cc->reset = s390_cpu_reset;
Andreas Färberc7396bb2013-01-20 19:41:06 +0100151
152 dc->vmsd = &vmstate_s390_cpu;
Andreas Färber29e4bcb2012-04-02 11:39:23 +0200153}
154
155static const TypeInfo s390_cpu_type_info = {
156 .name = TYPE_S390_CPU,
157 .parent = TYPE_CPU,
158 .instance_size = sizeof(S390CPU),
Andreas Färber8f22e0d2012-04-02 13:56:29 +0200159 .instance_init = s390_cpu_initfn,
Andreas Färberd5627ce2013-01-07 06:14:16 +0000160 .instance_finalize = s390_cpu_finalize,
Andreas Färber29e4bcb2012-04-02 11:39:23 +0200161 .abstract = false,
162 .class_size = sizeof(S390CPUClass),
163 .class_init = s390_cpu_class_init,
164};
165
166static void s390_cpu_register_types(void)
167{
168 type_register_static(&s390_cpu_type_info);
169}
170
171type_init(s390_cpu_register_types)