/[dynamips]/trunk/cpu.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/cpu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (11 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 7315 byte(s)
make working copy

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Management of CPU groups (for MP systems).
6 */
7
8 #define _GNU_SOURCE
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <stdarg.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/mman.h>
17 #include <fcntl.h>
18 #include <pthread.h>
19
20 #include "cpu.h"
21 #include "memory.h"
22 #include "device.h"
23 #include "mips64.h"
24 #include "mips64_cp0.h"
25 #include "mips64_exec.h"
26 #include "mips64_jit.h"
27 #include "ppc32.h"
28 #include "ppc32_exec.h"
29 #include "ppc32_jit.h"
30 #include "dynamips.h"
31 #include "vm.h"
32
33 /* Find a CPU in a group given its ID */
34 cpu_gen_t *cpu_group_find_id(cpu_group_t *group,u_int id)
35 {
36 cpu_gen_t *cpu;
37
38 if (!group)
39 return NULL;
40
41 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
42 if (cpu->id == id)
43 return cpu;
44
45 return NULL;
46 }
47
48 /* Find the highest CPU ID in a CPU group */
49 int cpu_group_find_highest_id(cpu_group_t *group,u_int *highest_id)
50 {
51 cpu_gen_t *cpu;
52 u_int max_id = 0;
53
54 if (!group || group->cpu_list)
55 return(-1);
56
57 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
58 if (cpu->id >= max_id)
59 max_id = cpu->id;
60
61 *highest_id = max_id;
62 return(0);
63 }
64
65 /* Add a CPU in a CPU group */
66 int cpu_group_add(cpu_group_t *group,cpu_gen_t *cpu)
67 {
68 if (!group)
69 return(-1);
70
71 /* check that we don't already have a CPU with this id */
72 if (cpu_group_find_id(group,cpu->id) != NULL) {
73 fprintf(stderr,"cpu_group_add: CPU%u already present in group.\n",
74 cpu->id);
75 return(-1);
76 }
77
78 cpu->next = group->cpu_list;
79 group->cpu_list = cpu;
80 return(0);
81 }
82
83 /* Create a new CPU group */
84 cpu_group_t *cpu_group_create(char *name)
85 {
86 cpu_group_t *group;
87
88 if (!(group = malloc(sizeof(*group))))
89 return NULL;
90
91 group->name = name;
92 group->cpu_list = NULL;
93 return group;
94 }
95
96 /* Delete a CPU group */
97 void cpu_group_delete(cpu_group_t *group)
98 {
99 cpu_gen_t *cpu,*next;
100
101 if (group != NULL) {
102 for(cpu=group->cpu_list;cpu;cpu=next) {
103 next = cpu->next;
104 cpu_delete(cpu);
105 }
106
107 free(group);
108 }
109 }
110
111 /* Rebuild the MTS subsystem for a CPU group */
112 int cpu_group_rebuild_mts(cpu_group_t *group)
113 {
114 cpu_gen_t *cpu;
115
116 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
117 cpu->mts_rebuild(cpu);
118
119 return(0);
120 }
121
122 /* Log a message for a CPU */
123 void cpu_log(cpu_gen_t *cpu,char *module,char *format,...)
124 {
125 char buffer[256];
126 va_list ap;
127
128 va_start(ap,format);
129 snprintf(buffer,sizeof(buffer),"CPU%u: %s",cpu->id,module);
130 vm_flog(cpu->vm,buffer,format,ap);
131 va_end(ap);
132 }
133
134 /* Create a new CPU */
135 cpu_gen_t *cpu_create(vm_instance_t *vm,u_int type,u_int id)
136 {
137 void *(*cpu_run_fn)(void *);
138 cpu_gen_t *cpu;
139
140 if (!(cpu = malloc(sizeof(*cpu))))
141 return NULL;
142
143 memset(cpu,0,sizeof(*cpu));
144 cpu->vm = vm;
145 cpu->id = id;
146 cpu->type = type;
147 cpu->state = CPU_STATE_SUSPENDED;
148
149 switch(cpu->type) {
150 case CPU_TYPE_MIPS64:
151 cpu->jit_op_array_size = MIPS_INSN_PER_PAGE;
152 CPU_MIPS64(cpu)->vm = vm;
153 CPU_MIPS64(cpu)->gen = cpu;
154 mips64_init(CPU_MIPS64(cpu));
155
156 cpu_run_fn = (void *)mips64_jit_run_cpu;
157
158 if (!cpu->vm->jit_use)
159 cpu_run_fn = (void *)mips64_exec_run_cpu;
160 else
161 mips64_jit_init(CPU_MIPS64(cpu));
162 break;
163
164 case CPU_TYPE_PPC32:
165 cpu->jit_op_array_size = PPC32_INSN_PER_PAGE;
166 CPU_PPC32(cpu)->vm = vm;
167 CPU_PPC32(cpu)->gen = cpu;
168 ppc32_init(CPU_PPC32(cpu));
169
170 cpu_run_fn = (void *)ppc32_jit_run_cpu;
171
172 if (!cpu->vm->jit_use)
173 cpu_run_fn = (void *)ppc32_exec_run_cpu;
174 else
175 ppc32_jit_init(CPU_PPC32(cpu));
176 break;
177
178 default:
179 fprintf(stderr,"CPU type %u is not supported yet\n",cpu->type);
180 abort();
181 break;
182 }
183
184 /* create the CPU thread execution */
185 if (pthread_create(&cpu->cpu_thread,NULL,cpu_run_fn,cpu) != 0) {
186 fprintf(stderr,"cpu_create: unable to create thread for CPU%u\n",id);
187 free(cpu);
188 return NULL;
189 }
190
191 return cpu;
192 }
193
194 /* Delete a CPU */
195 void cpu_delete(cpu_gen_t *cpu)
196 {
197 if (cpu) {
198 /* Stop activity of this CPU */
199 cpu_stop(cpu);
200 pthread_join(cpu->cpu_thread,NULL);
201
202 /* Free resources */
203 switch(cpu->type) {
204 case CPU_TYPE_MIPS64:
205 mips64_delete(CPU_MIPS64(cpu));
206 break;
207
208 case CPU_TYPE_PPC32:
209 ppc32_delete(CPU_PPC32(cpu));
210 break;
211 }
212
213 free(cpu);
214 }
215 }
216
217 /* Start a CPU */
218 void cpu_start(cpu_gen_t *cpu)
219 {
220 if (cpu) {
221 cpu_log(cpu,"CPU_STATE","Starting CPU (old state=%u)...\n",cpu->state);
222 cpu->state = CPU_STATE_RUNNING;
223 }
224 }
225
226 /* Stop a CPU */
227 void cpu_stop(cpu_gen_t *cpu)
228 {
229 if (cpu) {
230 cpu_log(cpu,"CPU_STATE","Halting CPU (old state=%u)...\n",cpu->state);
231 cpu->state = CPU_STATE_HALTED;
232 }
233 }
234
235 /* Start all CPUs of a CPU group */
236 void cpu_group_start_all_cpu(cpu_group_t *group)
237 {
238 cpu_gen_t *cpu;
239
240 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
241 cpu_start(cpu);
242 }
243
244 /* Stop all CPUs of a CPU group */
245 void cpu_group_stop_all_cpu(cpu_group_t *group)
246 {
247 cpu_gen_t *cpu;
248
249 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
250 cpu_stop(cpu);
251 }
252
253 /* Set a state of all CPUs of a CPU group */
254 void cpu_group_set_state(cpu_group_t *group,u_int state)
255 {
256 cpu_gen_t *cpu;
257
258 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
259 cpu->state = state;
260 }
261
262 /* Returns TRUE if all CPUs in a CPU group are inactive */
263 static int cpu_group_check_activity(cpu_group_t *group)
264 {
265 cpu_gen_t *cpu;
266
267 for(cpu=group->cpu_list;cpu;cpu=cpu->next) {
268 if (!cpu->cpu_thread_running)
269 continue;
270
271 if ((cpu->state == CPU_STATE_RUNNING) || !cpu->seq_state)
272 return(FALSE);
273 }
274
275 return(TRUE);
276 }
277
278 /* Synchronize on CPUs (all CPUs must be inactive) */
279 int cpu_group_sync_state(cpu_group_t *group)
280 {
281 cpu_gen_t *cpu;
282 m_tmcnt_t t1,t2;
283
284 /* Check that CPU activity is really suspended */
285 t1 = m_gettime();
286
287 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
288 cpu->seq_state = 0;
289
290 while(!cpu_group_check_activity(group)) {
291 t2 = m_gettime();
292
293 if (t2 > (t1 + 10000))
294 return(-1);
295
296 usleep(50000);
297 }
298
299 return(0);
300 }
301
302 /* Save state of all CPUs */
303 int cpu_group_save_state(cpu_group_t *group)
304 {
305 cpu_gen_t *cpu;
306
307 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
308 cpu->prev_state = cpu->state;
309
310 return(TRUE);
311 }
312
313 /* Restore state of all CPUs */
314 int cpu_group_restore_state(cpu_group_t *group)
315 {
316 cpu_gen_t *cpu;
317
318 for(cpu=group->cpu_list;cpu;cpu=cpu->next)
319 cpu->state = cpu->prev_state;
320
321 return(TRUE);
322 }
323
324 /* Virtual idle loop */
325 void cpu_idle_loop(cpu_gen_t *cpu)
326 {
327 struct timespec t_spc;
328 m_tmcnt_t expire;
329
330 expire = m_gettime_usec() + cpu->idle_sleep_time;
331
332 pthread_mutex_lock(&cpu->idle_mutex);
333 t_spc.tv_sec = expire / 1000000;
334 t_spc.tv_nsec = (expire % 1000000) * 1000;
335 pthread_cond_timedwait(&cpu->idle_cond,&cpu->idle_mutex,&t_spc);
336 pthread_mutex_unlock(&cpu->idle_mutex);
337 }
338
339 /* Break idle wait state */
340 void cpu_idle_break_wait(cpu_gen_t *cpu)
341 {
342 pthread_cond_signal(&cpu->idle_cond);
343 cpu->idle_count = 0;
344 }

  ViewVC Help
Powered by ViewVC 1.1.26