~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to target-openrisc/cpu.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * QEMU OpenRISC CPU
3
 
 *
4
 
 * Copyright (c) 2012 Jia Liu <proljc@gmail.com>
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 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 <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include "qemu/osdep.h"
21
 
#include "qapi/error.h"
22
 
#include "cpu.h"
23
 
#include "qemu-common.h"
24
 
#include "exec/exec-all.h"
25
 
 
26
 
static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
27
 
{
28
 
    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
29
 
 
30
 
    cpu->env.pc = value;
31
 
}
32
 
 
33
 
static bool openrisc_cpu_has_work(CPUState *cs)
34
 
{
35
 
    return cs->interrupt_request & (CPU_INTERRUPT_HARD |
36
 
                                    CPU_INTERRUPT_TIMER);
37
 
}
38
 
 
39
 
/* CPUClass::reset() */
40
 
static void openrisc_cpu_reset(CPUState *s)
41
 
{
42
 
    OpenRISCCPU *cpu = OPENRISC_CPU(s);
43
 
    OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
44
 
 
45
 
    occ->parent_reset(s);
46
 
 
47
 
#ifndef CONFIG_USER_ONLY
48
 
    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, tlb));
49
 
#else
50
 
    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, irq));
51
 
#endif
52
 
 
53
 
    tlb_flush(s, 1);
54
 
    /*tb_flush(&cpu->env);    FIXME: Do we need it?  */
55
 
 
56
 
    cpu->env.pc = 0x100;
57
 
    cpu->env.sr = SR_FO | SR_SM;
58
 
    s->exception_index = -1;
59
 
 
60
 
    cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
61
 
    cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
62
 
    cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
63
 
    cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
64
 
 
65
 
#ifndef CONFIG_USER_ONLY
66
 
    cpu->env.picmr = 0x00000000;
67
 
    cpu->env.picsr = 0x00000000;
68
 
 
69
 
    cpu->env.ttmr = 0x00000000;
70
 
    cpu->env.ttcr = 0x00000000;
71
 
#endif
72
 
}
73
 
 
74
 
static inline void set_feature(OpenRISCCPU *cpu, int feature)
75
 
{
76
 
    cpu->feature |= feature;
77
 
    cpu->env.cpucfgr = cpu->feature;
78
 
}
79
 
 
80
 
static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp)
81
 
{
82
 
    CPUState *cs = CPU(dev);
83
 
    OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(dev);
84
 
    Error *local_err = NULL;
85
 
 
86
 
    cpu_exec_realizefn(cs, &local_err);
87
 
    if (local_err != NULL) {
88
 
        error_propagate(errp, local_err);
89
 
        return;
90
 
    }
91
 
 
92
 
    qemu_init_vcpu(cs);
93
 
    cpu_reset(cs);
94
 
 
95
 
    occ->parent_realize(dev, errp);
96
 
}
97
 
 
98
 
static void openrisc_cpu_initfn(Object *obj)
99
 
{
100
 
    CPUState *cs = CPU(obj);
101
 
    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
102
 
    static int inited;
103
 
 
104
 
    cs->env_ptr = &cpu->env;
105
 
 
106
 
#ifndef CONFIG_USER_ONLY
107
 
    cpu_openrisc_mmu_init(cpu);
108
 
#endif
109
 
 
110
 
    if (tcg_enabled() && !inited) {
111
 
        inited = 1;
112
 
        openrisc_translate_init();
113
 
    }
114
 
}
115
 
 
116
 
/* CPU models */
117
 
 
118
 
static ObjectClass *openrisc_cpu_class_by_name(const char *cpu_model)
119
 
{
120
 
    ObjectClass *oc;
121
 
    char *typename;
122
 
 
123
 
    if (cpu_model == NULL) {
124
 
        return NULL;
125
 
    }
126
 
 
127
 
    typename = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, cpu_model);
128
 
    oc = object_class_by_name(typename);
129
 
    g_free(typename);
130
 
    if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_OPENRISC_CPU) ||
131
 
                       object_class_is_abstract(oc))) {
132
 
        return NULL;
133
 
    }
134
 
    return oc;
135
 
}
136
 
 
137
 
static void or1200_initfn(Object *obj)
138
 
{
139
 
    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
140
 
 
141
 
    set_feature(cpu, OPENRISC_FEATURE_OB32S);
142
 
    set_feature(cpu, OPENRISC_FEATURE_OF32S);
143
 
}
144
 
 
145
 
static void openrisc_any_initfn(Object *obj)
146
 
{
147
 
    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
148
 
 
149
 
    set_feature(cpu, OPENRISC_FEATURE_OB32S);
150
 
}
151
 
 
152
 
typedef struct OpenRISCCPUInfo {
153
 
    const char *name;
154
 
    void (*initfn)(Object *obj);
155
 
} OpenRISCCPUInfo;
156
 
 
157
 
static const OpenRISCCPUInfo openrisc_cpus[] = {
158
 
    { .name = "or1200",      .initfn = or1200_initfn },
159
 
    { .name = "any",         .initfn = openrisc_any_initfn },
160
 
};
161
 
 
162
 
static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
163
 
{
164
 
    OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc);
165
 
    CPUClass *cc = CPU_CLASS(occ);
166
 
    DeviceClass *dc = DEVICE_CLASS(oc);
167
 
 
168
 
    occ->parent_realize = dc->realize;
169
 
    dc->realize = openrisc_cpu_realizefn;
170
 
 
171
 
    occ->parent_reset = cc->reset;
172
 
    cc->reset = openrisc_cpu_reset;
173
 
 
174
 
    cc->class_by_name = openrisc_cpu_class_by_name;
175
 
    cc->has_work = openrisc_cpu_has_work;
176
 
    cc->do_interrupt = openrisc_cpu_do_interrupt;
177
 
    cc->cpu_exec_interrupt = openrisc_cpu_exec_interrupt;
178
 
    cc->dump_state = openrisc_cpu_dump_state;
179
 
    cc->set_pc = openrisc_cpu_set_pc;
180
 
    cc->gdb_read_register = openrisc_cpu_gdb_read_register;
181
 
    cc->gdb_write_register = openrisc_cpu_gdb_write_register;
182
 
#ifdef CONFIG_USER_ONLY
183
 
    cc->handle_mmu_fault = openrisc_cpu_handle_mmu_fault;
184
 
#else
185
 
    cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug;
186
 
    dc->vmsd = &vmstate_openrisc_cpu;
187
 
#endif
188
 
    cc->gdb_num_core_regs = 32 + 3;
189
 
}
190
 
 
191
 
static void cpu_register(const OpenRISCCPUInfo *info)
192
 
{
193
 
    TypeInfo type_info = {
194
 
        .parent = TYPE_OPENRISC_CPU,
195
 
        .instance_size = sizeof(OpenRISCCPU),
196
 
        .instance_init = info->initfn,
197
 
        .class_size = sizeof(OpenRISCCPUClass),
198
 
    };
199
 
 
200
 
    type_info.name = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, info->name);
201
 
    type_register(&type_info);
202
 
    g_free((void *)type_info.name);
203
 
}
204
 
 
205
 
static const TypeInfo openrisc_cpu_type_info = {
206
 
    .name = TYPE_OPENRISC_CPU,
207
 
    .parent = TYPE_CPU,
208
 
    .instance_size = sizeof(OpenRISCCPU),
209
 
    .instance_init = openrisc_cpu_initfn,
210
 
    .abstract = true,
211
 
    .class_size = sizeof(OpenRISCCPUClass),
212
 
    .class_init = openrisc_cpu_class_init,
213
 
};
214
 
 
215
 
static void openrisc_cpu_register_types(void)
216
 
{
217
 
    int i;
218
 
 
219
 
    type_register_static(&openrisc_cpu_type_info);
220
 
    for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) {
221
 
        cpu_register(&openrisc_cpus[i]);
222
 
    }
223
 
}
224
 
 
225
 
OpenRISCCPU *cpu_openrisc_init(const char *cpu_model)
226
 
{
227
 
    return OPENRISC_CPU(cpu_generic_init(TYPE_OPENRISC_CPU, cpu_model));
228
 
}
229
 
 
230
 
/* Sort alphabetically by type name, except for "any". */
231
 
static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b)
232
 
{
233
 
    ObjectClass *class_a = (ObjectClass *)a;
234
 
    ObjectClass *class_b = (ObjectClass *)b;
235
 
    const char *name_a, *name_b;
236
 
 
237
 
    name_a = object_class_get_name(class_a);
238
 
    name_b = object_class_get_name(class_b);
239
 
    if (strcmp(name_a, "any-" TYPE_OPENRISC_CPU) == 0) {
240
 
        return 1;
241
 
    } else if (strcmp(name_b, "any-" TYPE_OPENRISC_CPU) == 0) {
242
 
        return -1;
243
 
    } else {
244
 
        return strcmp(name_a, name_b);
245
 
    }
246
 
}
247
 
 
248
 
static void openrisc_cpu_list_entry(gpointer data, gpointer user_data)
249
 
{
250
 
    ObjectClass *oc = data;
251
 
    CPUListState *s = user_data;
252
 
    const char *typename;
253
 
    char *name;
254
 
 
255
 
    typename = object_class_get_name(oc);
256
 
    name = g_strndup(typename,
257
 
                     strlen(typename) - strlen("-" TYPE_OPENRISC_CPU));
258
 
    (*s->cpu_fprintf)(s->file, "  %s\n",
259
 
                      name);
260
 
    g_free(name);
261
 
}
262
 
 
263
 
void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
264
 
{
265
 
    CPUListState s = {
266
 
        .file = f,
267
 
        .cpu_fprintf = cpu_fprintf,
268
 
    };
269
 
    GSList *list;
270
 
 
271
 
    list = object_class_get_list(TYPE_OPENRISC_CPU, false);
272
 
    list = g_slist_sort(list, openrisc_cpu_list_compare);
273
 
    (*cpu_fprintf)(f, "Available CPUs:\n");
274
 
    g_slist_foreach(list, openrisc_cpu_list_entry, &s);
275
 
    g_slist_free(list);
276
 
}
277
 
 
278
 
type_init(openrisc_cpu_register_types)