Statistics
| Branch: | Revision:

root / target-openrisc / cpu.c @ 14a10fc3

History | View | Annotate | Download (7 kB)

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 "cpu.h"
21
#include "qemu-common.h"
22

    
23
static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
24
{
25
    OpenRISCCPU *cpu = OPENRISC_CPU(cs);
26

    
27
    cpu->env.pc = value;
28
}
29

    
30
/* CPUClass::reset() */
31
static void openrisc_cpu_reset(CPUState *s)
32
{
33
    OpenRISCCPU *cpu = OPENRISC_CPU(s);
34
    OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
35

    
36
    occ->parent_reset(s);
37

    
38
    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints));
39

    
40
    tlb_flush(&cpu->env, 1);
41
    /*tb_flush(&cpu->env);    FIXME: Do we need it?  */
42

    
43
    cpu->env.pc = 0x100;
44
    cpu->env.sr = SR_FO | SR_SM;
45
    cpu->env.exception_index = -1;
46

    
47
    cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
48
    cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
49
    cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
50
    cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
51

    
52
#ifndef CONFIG_USER_ONLY
53
    cpu->env.picmr = 0x00000000;
54
    cpu->env.picsr = 0x00000000;
55

    
56
    cpu->env.ttmr = 0x00000000;
57
    cpu->env.ttcr = 0x00000000;
58
#endif
59
}
60

    
61
static inline void set_feature(OpenRISCCPU *cpu, int feature)
62
{
63
    cpu->feature |= feature;
64
    cpu->env.cpucfgr = cpu->feature;
65
}
66

    
67
static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp)
68
{
69
    CPUState *cs = CPU(dev);
70
    OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(dev);
71

    
72
    qemu_init_vcpu(cs);
73
    cpu_reset(cs);
74

    
75
    occ->parent_realize(dev, errp);
76
}
77

    
78
static void openrisc_cpu_initfn(Object *obj)
79
{
80
    CPUState *cs = CPU(obj);
81
    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
82
    static int inited;
83

    
84
    cs->env_ptr = &cpu->env;
85
    cpu_exec_init(&cpu->env);
86

    
87
#ifndef CONFIG_USER_ONLY
88
    cpu_openrisc_mmu_init(cpu);
89
#endif
90

    
91
    if (tcg_enabled() && !inited) {
92
        inited = 1;
93
        openrisc_translate_init();
94
    }
95
}
96

    
97
/* CPU models */
98

    
99
static ObjectClass *openrisc_cpu_class_by_name(const char *cpu_model)
100
{
101
    ObjectClass *oc;
102
    char *typename;
103

    
104
    if (cpu_model == NULL) {
105
        return NULL;
106
    }
107

    
108
    typename = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, cpu_model);
109
    oc = object_class_by_name(typename);
110
    g_free(typename);
111
    if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_OPENRISC_CPU) ||
112
                       object_class_is_abstract(oc))) {
113
        return NULL;
114
    }
115
    return oc;
116
}
117

    
118
static void or1200_initfn(Object *obj)
119
{
120
    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
121

    
122
    set_feature(cpu, OPENRISC_FEATURE_OB32S);
123
    set_feature(cpu, OPENRISC_FEATURE_OF32S);
124
}
125

    
126
static void openrisc_any_initfn(Object *obj)
127
{
128
    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
129

    
130
    set_feature(cpu, OPENRISC_FEATURE_OB32S);
131
}
132

    
133
typedef struct OpenRISCCPUInfo {
134
    const char *name;
135
    void (*initfn)(Object *obj);
136
} OpenRISCCPUInfo;
137

    
138
static const OpenRISCCPUInfo openrisc_cpus[] = {
139
    { .name = "or1200",      .initfn = or1200_initfn },
140
    { .name = "any",         .initfn = openrisc_any_initfn },
141
};
142

    
143
static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
144
{
145
    OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc);
146
    CPUClass *cc = CPU_CLASS(occ);
147
    DeviceClass *dc = DEVICE_CLASS(oc);
148

    
149
    occ->parent_realize = dc->realize;
150
    dc->realize = openrisc_cpu_realizefn;
151

    
152
    occ->parent_reset = cc->reset;
153
    cc->reset = openrisc_cpu_reset;
154

    
155
    cc->class_by_name = openrisc_cpu_class_by_name;
156
    cc->do_interrupt = openrisc_cpu_do_interrupt;
157
    cc->dump_state = openrisc_cpu_dump_state;
158
    cc->set_pc = openrisc_cpu_set_pc;
159
    cc->gdb_read_register = openrisc_cpu_gdb_read_register;
160
    cc->gdb_write_register = openrisc_cpu_gdb_write_register;
161
#ifndef CONFIG_USER_ONLY
162
    cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug;
163
    dc->vmsd = &vmstate_openrisc_cpu;
164
#endif
165
    cc->gdb_num_core_regs = 32 + 3;
166
}
167

    
168
static void cpu_register(const OpenRISCCPUInfo *info)
169
{
170
    TypeInfo type_info = {
171
        .parent = TYPE_OPENRISC_CPU,
172
        .instance_size = sizeof(OpenRISCCPU),
173
        .instance_init = info->initfn,
174
        .class_size = sizeof(OpenRISCCPUClass),
175
    };
176

    
177
    type_info.name = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, info->name);
178
    type_register(&type_info);
179
    g_free((void *)type_info.name);
180
}
181

    
182
static const TypeInfo openrisc_cpu_type_info = {
183
    .name = TYPE_OPENRISC_CPU,
184
    .parent = TYPE_CPU,
185
    .instance_size = sizeof(OpenRISCCPU),
186
    .instance_init = openrisc_cpu_initfn,
187
    .abstract = true,
188
    .class_size = sizeof(OpenRISCCPUClass),
189
    .class_init = openrisc_cpu_class_init,
190
};
191

    
192
static void openrisc_cpu_register_types(void)
193
{
194
    int i;
195

    
196
    type_register_static(&openrisc_cpu_type_info);
197
    for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) {
198
        cpu_register(&openrisc_cpus[i]);
199
    }
200
}
201

    
202
OpenRISCCPU *cpu_openrisc_init(const char *cpu_model)
203
{
204
    OpenRISCCPU *cpu;
205
    ObjectClass *oc;
206

    
207
    oc = openrisc_cpu_class_by_name(cpu_model);
208
    if (oc == NULL) {
209
        return NULL;
210
    }
211
    cpu = OPENRISC_CPU(object_new(object_class_get_name(oc)));
212
    cpu->env.cpu_model_str = cpu_model;
213

    
214
    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
215

    
216
    return cpu;
217
}
218

    
219
/* Sort alphabetically by type name, except for "any". */
220
static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b)
221
{
222
    ObjectClass *class_a = (ObjectClass *)a;
223
    ObjectClass *class_b = (ObjectClass *)b;
224
    const char *name_a, *name_b;
225

    
226
    name_a = object_class_get_name(class_a);
227
    name_b = object_class_get_name(class_b);
228
    if (strcmp(name_a, "any-" TYPE_OPENRISC_CPU) == 0) {
229
        return 1;
230
    } else if (strcmp(name_b, "any-" TYPE_OPENRISC_CPU) == 0) {
231
        return -1;
232
    } else {
233
        return strcmp(name_a, name_b);
234
    }
235
}
236

    
237
static void openrisc_cpu_list_entry(gpointer data, gpointer user_data)
238
{
239
    ObjectClass *oc = data;
240
    CPUListState *s = user_data;
241
    const char *typename;
242
    char *name;
243

    
244
    typename = object_class_get_name(oc);
245
    name = g_strndup(typename,
246
                     strlen(typename) - strlen("-" TYPE_OPENRISC_CPU));
247
    (*s->cpu_fprintf)(s->file, "  %s\n",
248
                      name);
249
    g_free(name);
250
}
251

    
252
void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
253
{
254
    CPUListState s = {
255
        .file = f,
256
        .cpu_fprintf = cpu_fprintf,
257
    };
258
    GSList *list;
259

    
260
    list = object_class_get_list(TYPE_OPENRISC_CPU, false);
261
    list = g_slist_sort(list, openrisc_cpu_list_compare);
262
    (*cpu_fprintf)(f, "Available CPUs:\n");
263
    g_slist_foreach(list, openrisc_cpu_list_entry, &s);
264
    g_slist_free(list);
265
}
266

    
267
type_init(openrisc_cpu_register_types)