Add qemu 2.4.0
[kvmfornfv.git] / qemu / target-mips / cpu.c
1 /*
2  * QEMU MIPS CPU
3  *
4  * Copyright (c) 2012 SUSE LINUX Products GmbH
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see
18  * <http://www.gnu.org/licenses/lgpl-2.1.html>
19  */
20
21 #include "cpu.h"
22 #include "kvm_mips.h"
23 #include "qemu-common.h"
24 #include "sysemu/kvm.h"
25
26
27 static void mips_cpu_set_pc(CPUState *cs, vaddr value)
28 {
29     MIPSCPU *cpu = MIPS_CPU(cs);
30     CPUMIPSState *env = &cpu->env;
31
32     env->active_tc.PC = value & ~(target_ulong)1;
33     if (value & 1) {
34         env->hflags |= MIPS_HFLAG_M16;
35     } else {
36         env->hflags &= ~(MIPS_HFLAG_M16);
37     }
38 }
39
40 static void mips_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
41 {
42     MIPSCPU *cpu = MIPS_CPU(cs);
43     CPUMIPSState *env = &cpu->env;
44
45     env->active_tc.PC = tb->pc;
46     env->hflags &= ~MIPS_HFLAG_BMASK;
47     env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
48 }
49
50 static bool mips_cpu_has_work(CPUState *cs)
51 {
52     MIPSCPU *cpu = MIPS_CPU(cs);
53     CPUMIPSState *env = &cpu->env;
54     bool has_work = false;
55
56     /* It is implementation dependent if non-enabled interrupts
57        wake-up the CPU, however most of the implementations only
58        check for interrupts that can be taken. */
59     if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
60         cpu_mips_hw_interrupts_pending(env)) {
61         has_work = true;
62     }
63
64     /* MIPS-MT has the ability to halt the CPU.  */
65     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
66         /* The QEMU model will issue an _WAKE request whenever the CPUs
67            should be woken up.  */
68         if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
69             has_work = true;
70         }
71
72         if (!mips_vpe_active(env)) {
73             has_work = false;
74         }
75     }
76     return has_work;
77 }
78
79 /* CPUClass::reset() */
80 static void mips_cpu_reset(CPUState *s)
81 {
82     MIPSCPU *cpu = MIPS_CPU(s);
83     MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
84     CPUMIPSState *env = &cpu->env;
85
86     mcc->parent_reset(s);
87
88     memset(env, 0, offsetof(CPUMIPSState, mvp));
89     tlb_flush(s, 1);
90
91     cpu_state_reset(env);
92
93 #ifndef CONFIG_USER_ONLY
94     if (kvm_enabled()) {
95         kvm_mips_reset_vcpu(cpu);
96     }
97 #endif
98 }
99
100 static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
101 {
102     CPUState *cs = CPU(dev);
103     MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
104
105     cpu_reset(cs);
106     qemu_init_vcpu(cs);
107
108     mcc->parent_realize(dev, errp);
109 }
110
111 static void mips_cpu_initfn(Object *obj)
112 {
113     CPUState *cs = CPU(obj);
114     MIPSCPU *cpu = MIPS_CPU(obj);
115     CPUMIPSState *env = &cpu->env;
116
117     cs->env_ptr = env;
118     cpu_exec_init(cs, &error_abort);
119
120     if (tcg_enabled()) {
121         mips_tcg_init();
122     }
123 }
124
125 static void mips_cpu_class_init(ObjectClass *c, void *data)
126 {
127     MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
128     CPUClass *cc = CPU_CLASS(c);
129     DeviceClass *dc = DEVICE_CLASS(c);
130
131     mcc->parent_realize = dc->realize;
132     dc->realize = mips_cpu_realizefn;
133
134     mcc->parent_reset = cc->reset;
135     cc->reset = mips_cpu_reset;
136
137     cc->has_work = mips_cpu_has_work;
138     cc->do_interrupt = mips_cpu_do_interrupt;
139     cc->cpu_exec_interrupt = mips_cpu_exec_interrupt;
140     cc->dump_state = mips_cpu_dump_state;
141     cc->set_pc = mips_cpu_set_pc;
142     cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
143     cc->gdb_read_register = mips_cpu_gdb_read_register;
144     cc->gdb_write_register = mips_cpu_gdb_write_register;
145 #ifdef CONFIG_USER_ONLY
146     cc->handle_mmu_fault = mips_cpu_handle_mmu_fault;
147 #else
148     cc->do_unassigned_access = mips_cpu_unassigned_access;
149     cc->do_unaligned_access = mips_cpu_do_unaligned_access;
150     cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
151     cc->vmsd = &vmstate_mips_cpu;
152 #endif
153
154     cc->gdb_num_core_regs = 73;
155     cc->gdb_stop_before_watchpoint = true;
156 }
157
158 static const TypeInfo mips_cpu_type_info = {
159     .name = TYPE_MIPS_CPU,
160     .parent = TYPE_CPU,
161     .instance_size = sizeof(MIPSCPU),
162     .instance_init = mips_cpu_initfn,
163     .abstract = false,
164     .class_size = sizeof(MIPSCPUClass),
165     .class_init = mips_cpu_class_init,
166 };
167
168 static void mips_cpu_register_types(void)
169 {
170     type_register_static(&mips_cpu_type_info);
171 }
172
173 type_init(mips_cpu_register_types)